diff options
Diffstat (limited to 'deps/v8/test/cctest')
49 files changed, 7134 insertions, 2406 deletions
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript index 703813776..0197178cf 100644 --- a/deps/v8/test/cctest/SConscript +++ b/deps/v8/test/cctest/SConscript @@ -41,8 +41,8 @@ SOURCES = { 'test-alloc.cc', 'test-api.cc', 'test-ast.cc', - 'test-bignum.cc', 'test-bignum-dtoa.cc', + 'test-bignum.cc', 'test-circular-queue.cc', 'test-compiler.cc', 'test-conversions.cc', @@ -59,15 +59,17 @@ SOURCES = { 'test-flags.cc', 'test-func-name-inference.cc', 'test-hashmap.cc', - 'test-heap.cc', 'test-heap-profiler.cc', + 'test-heap.cc', 'test-list.cc', 'test-liveedit.cc', 'test-lock.cc', - 'test-log.cc', + 'test-lockers.cc', 'test-log-utils.cc', + 'test-log.cc', 'test-mark-compact.cc', 'test-parsing.cc', + 'test-platform-tls.cc', 'test-profile-generator.cc', 'test-regexp.cc', 'test-reloc-info.cc', @@ -78,7 +80,6 @@ SOURCES = { 'test-strtod.cc', 'test-thread-termination.cc', 'test-threads.cc', - 'test-type-info.cc', 'test-unbound-queue.cc', 'test-utils.cc', 'test-version.cc' @@ -95,7 +96,8 @@ SOURCES = { 'arch:x64': ['test-assembler-x64.cc', 'test-macro-assembler-x64.cc', 'test-log-stack-tracer.cc'], - 'arch:mips': ['test-assembler-mips.cc', 'test-mips.cc'], + 'arch:mips': ['test-assembler-mips.cc', + 'test-disasm-mips.cc'], 'os:linux': ['test-platform-linux.cc'], 'os:macos': ['test-platform-macos.cc'], 'os:nullos': ['test-platform-nullos.cc'], diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp index aa2b35583..1d54e8cf5 100644 --- a/deps/v8/test/cctest/cctest.gyp +++ b/deps/v8/test/cctest/cctest.gyp @@ -1,4 +1,4 @@ -# Copyright 2010 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: @@ -26,31 +26,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { - 'target_defaults': { - 'conditions': [ - ['OS!="mac"', { - # TODO(sgjesse): This is currently copied from v8.gyp, should probably - # be refactored. - 'conditions': [ - ['v8_target_arch=="arm"', { - 'defines': [ - 'V8_TARGET_ARCH_ARM', - ], - }], - ['v8_target_arch=="ia32"', { - 'defines': [ - 'V8_TARGET_ARCH_IA32', - ], - }], - ['v8_target_arch=="x64"', { - 'defines': [ - 'V8_TARGET_ARCH_X64', - ], - }], - ], - }], - ], - }, + 'includes': [ '../../build/v8-features.gypi' ], 'targets': [ { 'target_name': 'cctest', @@ -93,6 +69,7 @@ 'test-list.cc', 'test-liveedit.cc', 'test-lock.cc', + 'test-lockers.cc', 'test-log.cc', 'test-log-utils.cc', 'test-mark-compact.cc', @@ -107,7 +84,6 @@ 'test-strtod.cc', 'test-thread-termination.cc', 'test-threads.cc', - 'test-type-info.cc', 'test-unbound-queue.cc', 'test-utils.cc', 'test-version.cc' @@ -136,7 +112,7 @@ ['v8_target_arch=="mips"', { 'sources': [ 'test-assembler-mips.cc', - 'test-mips.cc', + 'test-disasm-mips.cc', ], }], [ 'OS=="linux"', { diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h index 404b692b2..b0b8eb720 100644 --- a/deps/v8/test/cctest/cctest.h +++ b/deps/v8/test/cctest/cctest.h @@ -88,7 +88,8 @@ class ApiTestFuzzer: public v8::internal::Thread { public: void CallTest(); explicit ApiTestFuzzer(int num) - : test_number_(num), + : Thread("ApiTestFuzzer"), + test_number_(num), gate_(v8::internal::OS::CreateSemaphore(0)), active_(true) { } @@ -97,7 +98,11 @@ class ApiTestFuzzer: public v8::internal::Thread { // The ApiTestFuzzer is also a Thread, so it has a Run method. virtual void Run(); - enum PartOfTest { FIRST_PART, SECOND_PART }; + enum PartOfTest { FIRST_PART, + SECOND_PART, + THIRD_PART, + FOURTH_PART, + LAST_PART = FOURTH_PART }; static void Setup(PartOfTest part); static void RunAllTests(); diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index e573eb29b..6e7824f2f 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -30,17 +30,9 @@ prefix cctest test-api/Bug*: FAIL ############################################################################## -# BUG(281): This test fails on some Linuxes. -test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux - # 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 @@ -59,10 +51,11 @@ test-api/OutOfMemoryNested: SKIP test-log/ProfLazyMode: SKIP # BUG(945): Socket connect fails on ARM +test-debug/DebuggerAgent: SKIP test-debug/DebuggerAgentProtocolOverflowHeader: SKIP test-sockets/Socket: SKIP -# BUG(1075): Some deserialization tests fail om ARM +# BUG(1075): Unresolved crashes. test-serialize/Deserialize: SKIP test-serialize/DeserializeFromSecondSerializationAndRunScript2: SKIP test-serialize/DeserializeAndRunScript2: SKIP @@ -78,22 +71,5 @@ test-debug/DebugBreakLoop: SKIP ############################################################################## [ $arch == mips ] -test-accessors: SKIP -test-alloc: SKIP -test-api: SKIP -test-compiler: SKIP -test-cpu-profiler: SKIP -test-debug: SKIP -test-decls: SKIP -test-func-name-inference: SKIP -test-heap: SKIP -test-heap-profiler: SKIP -test-log: SKIP -test-log-utils: SKIP -test-mark-compact: SKIP -test-regexp: SKIP +test-deoptimization: SKIP test-serialize: SKIP -test-sockets: SKIP -test-strings: SKIP -test-threads: SKIP -test-thread-termination: SKIP diff --git a/deps/v8/test/cctest/test-accessors.cc b/deps/v8/test/cctest/test-accessors.cc index 25f5c3951..028f82f3d 100644 --- a/deps/v8/test/cctest/test-accessors.cc +++ b/deps/v8/test/cctest/test-accessors.cc @@ -243,7 +243,7 @@ static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name, ApiTestFuzzer::Fuzz(); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); - i::Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); return v8::Integer::New(17); @@ -397,9 +397,9 @@ static v8::Handle<Value> StackCheck(Local<String> name, for (int i = 0; !iter.done(); i++) { i::StackFrame* frame = iter.frame(); CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT)); - CHECK(frame->code()->IsCode()); + i::Code* code = frame->LookupCode(); + CHECK(code->IsCode()); i::Address pc = frame->pc(); - i::Code* code = frame->code(); CHECK(code->contains(pc)); iter.Advance(); } diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc index d2a28d7f4..4d9c218a4 100644 --- a/deps/v8/test/cctest/test-alloc.cc +++ b/deps/v8/test/cctest/test-alloc.cc @@ -27,7 +27,6 @@ #include "v8.h" #include "accessors.h" -#include "top.h" #include "cctest.h" @@ -38,13 +37,14 @@ using namespace v8::internal; static MaybeObject* AllocateAfterFailures() { static int attempts = 0; if (++attempts < 3) return Failure::RetryAfterGC(); + Heap* heap = Isolate::Current()->heap(); // New space. - NewSpace* new_space = Heap::new_space(); + NewSpace* new_space = heap->new_space(); static const int kNewSpaceFillerSize = ByteArray::SizeFor(0); while (new_space->Available() > kNewSpaceFillerSize) { int available_before = static_cast<int>(new_space->Available()); - CHECK(!Heap::AllocateByteArray(0)->IsFailure()); + CHECK(!heap->AllocateByteArray(0)->IsFailure()); if (available_before == new_space->Available()) { // It seems that we are avoiding new space allocations when // allocation is forced, so no need to fill up new space @@ -52,45 +52,46 @@ static MaybeObject* AllocateAfterFailures() { break; } } - CHECK(!Heap::AllocateByteArray(100)->IsFailure()); - CHECK(!Heap::AllocateFixedArray(100, NOT_TENURED)->IsFailure()); + CHECK(!heap->AllocateByteArray(100)->IsFailure()); + CHECK(!heap->AllocateFixedArray(100, NOT_TENURED)->IsFailure()); // Make sure we can allocate through optimized allocation functions // for specific kinds. - CHECK(!Heap::AllocateFixedArray(100)->IsFailure()); - CHECK(!Heap::AllocateHeapNumber(0.42)->IsFailure()); - CHECK(!Heap::AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure()); - Object* object = - Heap::AllocateJSObject(*Top::object_function())->ToObjectChecked(); - CHECK(!Heap::CopyJSObject(JSObject::cast(object))->IsFailure()); + CHECK(!heap->AllocateFixedArray(100)->IsFailure()); + CHECK(!heap->AllocateHeapNumber(0.42)->IsFailure()); + CHECK(!heap->AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure()); + Object* object = heap->AllocateJSObject( + *Isolate::Current()->object_function())->ToObjectChecked(); + CHECK(!heap->CopyJSObject(JSObject::cast(object))->IsFailure()); // Old data space. - OldSpace* old_data_space = Heap::old_data_space(); + OldSpace* old_data_space = heap->old_data_space(); static const int kOldDataSpaceFillerSize = ByteArray::SizeFor(0); while (old_data_space->Available() > kOldDataSpaceFillerSize) { - CHECK(!Heap::AllocateByteArray(0, TENURED)->IsFailure()); + CHECK(!heap->AllocateByteArray(0, TENURED)->IsFailure()); } - CHECK(!Heap::AllocateRawAsciiString(100, TENURED)->IsFailure()); + CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure()); // Large object space. - while (!Heap::OldGenerationAllocationLimitReached()) { - CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure()); + while (!heap->OldGenerationAllocationLimitReached()) { + CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); } - CHECK(!Heap::AllocateFixedArray(10000, TENURED)->IsFailure()); + CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); // Map space. - MapSpace* map_space = Heap::map_space(); + MapSpace* map_space = heap->map_space(); static const int kMapSpaceFillerSize = Map::kSize; InstanceType instance_type = JS_OBJECT_TYPE; int instance_size = JSObject::kHeaderSize; while (map_space->Available() > kMapSpaceFillerSize) { - CHECK(!Heap::AllocateMap(instance_type, instance_size)->IsFailure()); + CHECK(!heap->AllocateMap(instance_type, instance_size)->IsFailure()); } - CHECK(!Heap::AllocateMap(instance_type, instance_size)->IsFailure()); + CHECK(!heap->AllocateMap(instance_type, instance_size)->IsFailure()); // Test that we can allocate in old pointer space and code space. - CHECK(!Heap::AllocateFixedArray(100, TENURED)->IsFailure()); - CHECK(!Heap::CopyCode(Builtins::builtin(Builtins::Illegal))->IsFailure()); + CHECK(!heap->AllocateFixedArray(100, TENURED)->IsFailure()); + CHECK(!heap->CopyCode(Isolate::Current()->builtins()->builtin( + Builtins::kIllegal))->IsFailure()); // Return success. return Smi::FromInt(42); @@ -98,7 +99,7 @@ static MaybeObject* AllocateAfterFailures() { static Handle<Object> Test() { - CALL_HEAP_FUNCTION(AllocateAfterFailures(), Object); + CALL_HEAP_FUNCTION(ISOLATE, AllocateAfterFailures(), Object); } @@ -129,19 +130,20 @@ TEST(StressJS) { v8::HandleScope scope; env->Enter(); Handle<JSFunction> function = - Factory::NewFunction(Factory::function_symbol(), Factory::null_value()); + FACTORY->NewFunction(FACTORY->function_symbol(), FACTORY->null_value()); // Force the creation of an initial map and set the code to // something empty. - Factory::NewJSObject(function); - function->ReplaceCode(Builtins::builtin(Builtins::EmptyFunction)); + FACTORY->NewJSObject(function); + function->ReplaceCode(Isolate::Current()->builtins()->builtin( + Builtins::kEmptyFunction)); // Patch the map to have an accessor for "get". Handle<Map> map(function->initial_map()); Handle<DescriptorArray> instance_descriptors(map->instance_descriptors()); - Handle<Proxy> proxy = Factory::NewProxy(&kDescriptor); - instance_descriptors = Factory::CopyAppendProxyDescriptor( + Handle<Foreign> foreign = FACTORY->NewForeign(&kDescriptor); + instance_descriptors = FACTORY->CopyAppendForeignDescriptor( instance_descriptors, - Factory::NewStringFromAscii(Vector<const char>("get", 3)), - proxy, + FACTORY->NewStringFromAscii(Vector<const char>("get", 3)), + foreign, static_cast<PropertyAttributes>(0)); map->set_instance_descriptors(*instance_descriptors); // Add the Foo constructor the global object. @@ -183,7 +185,8 @@ class Block { TEST(CodeRange) { const int code_range_size = 16*MB; - CodeRange::Setup(code_range_size); + OS::Setup(); + Isolate::Current()->code_range()->Setup(code_range_size); int current_allocated = 0; int total_allocated = 0; List<Block> blocks(1000); @@ -195,14 +198,17 @@ TEST(CodeRange) { size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) + Pseudorandom() % 5000 + 1; size_t allocated = 0; - void* base = CodeRange::AllocateRawMemory(requested, &allocated); + void* base = Isolate::Current()->code_range()-> + AllocateRawMemory(requested, &allocated); + CHECK(base != NULL); blocks.Add(Block(base, static_cast<int>(allocated))); current_allocated += static_cast<int>(allocated); total_allocated += static_cast<int>(allocated); } else { // Free a block. int index = Pseudorandom() % blocks.length(); - CodeRange::FreeRawMemory(blocks[index].base, blocks[index].size); + Isolate::Current()->code_range()->FreeRawMemory( + blocks[index].base, blocks[index].size); current_allocated -= blocks[index].size; if (index < blocks.length() - 1) { blocks[index] = blocks.RemoveLast(); @@ -212,5 +218,5 @@ TEST(CodeRange) { } } - CodeRange::TearDown(); + Isolate::Current()->code_range()->TearDown(); } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index f450a3459..097743dd1 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -1,4 +1,4 @@ -// Copyright 2007-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: @@ -30,17 +30,17 @@ #include "v8.h" #include "api.h" +#include "isolate.h" #include "compilation-cache.h" #include "execution.h" #include "snapshot.h" #include "platform.h" -#include "top.h" #include "utils.h" #include "cctest.h" #include "parser.h" #include "unicode-inl.h" -static const bool kLogThreading = true; +static const bool kLogThreading = false; static bool IsNaN(double x) { #ifdef WIN32 @@ -50,15 +50,27 @@ static bool IsNaN(double x) { #endif } -using ::v8::ObjectTemplate; -using ::v8::Value; +using ::v8::AccessorInfo; +using ::v8::Arguments; using ::v8::Context; +using ::v8::Extension; +using ::v8::Function; +using ::v8::FunctionTemplate; +using ::v8::Handle; +using ::v8::HandleScope; using ::v8::Local; -using ::v8::String; +using ::v8::Message; +using ::v8::MessageCallback; +using ::v8::Object; +using ::v8::ObjectTemplate; +using ::v8::Persistent; using ::v8::Script; -using ::v8::Function; -using ::v8::AccessorInfo; -using ::v8::Extension; +using ::v8::StackTrace; +using ::v8::String; +using ::v8::TryCatch; +using ::v8::Undefined; +using ::v8::V8; +using ::v8::Value; namespace i = ::i; @@ -191,8 +203,6 @@ THREADED_TEST(ReceiverSignature) { } - - THREADED_TEST(ArgumentSignature) { v8::HandleScope scope; LocalContext env; @@ -394,11 +404,11 @@ THREADED_TEST(ScriptUsingStringResource) { CHECK(source->IsExternal()); CHECK_EQ(resource, static_cast<TestResource*>(source->GetExternalStringResource())); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + v8::internal::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestResource::dispose_count); } @@ -415,11 +425,11 @@ THREADED_TEST(ScriptUsingAsciiStringResource) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestAsciiResource::dispose_count); } @@ -432,19 +442,19 @@ THREADED_TEST(ScriptMakingExternalString) { LocalContext env; Local<String> source = String::New(two_byte_source); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now bool success = source->MakeExternal(new TestResource(two_byte_source)); CHECK(success); Local<Script> script = Script::Compile(source); Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestResource::dispose_count); } @@ -457,8 +467,8 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { LocalContext env; Local<String> source = v8_str(c_source); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now bool success = source->MakeExternal( new TestAsciiResource(i::StrDup(c_source))); CHECK(success); @@ -466,11 +476,11 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestAsciiResource::dispose_count); } @@ -480,8 +490,8 @@ TEST(MakingExternalStringConditions) { LocalContext env; // Free some space in the new space so that we can check freshness. - i::Heap::CollectGarbage(i::NEW_SPACE); - i::Heap::CollectGarbage(i::NEW_SPACE); + HEAP->CollectGarbage(i::NEW_SPACE); + HEAP->CollectGarbage(i::NEW_SPACE); uint16_t* two_byte_string = AsciiToTwoByteString("small"); Local<String> small_string = String::New(two_byte_string); @@ -490,8 +500,8 @@ TEST(MakingExternalStringConditions) { // 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. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); @@ -526,15 +536,15 @@ TEST(MakingExternalAsciiStringConditions) { LocalContext env; // Free some space in the new space so that we can check freshness. - i::Heap::CollectGarbage(i::NEW_SPACE); - i::Heap::CollectGarbage(i::NEW_SPACE); + HEAP->CollectGarbage(i::NEW_SPACE); + HEAP->CollectGarbage(i::NEW_SPACE); Local<String> small_string = String::New("small"); // 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. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); @@ -566,13 +576,13 @@ THREADED_TEST(UsingExternalString) { String::NewExternal(new TestResource(two_byte_string)); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now - i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring); + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now + i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - i::Heap::CollectAllGarbage(false); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } @@ -584,13 +594,13 @@ THREADED_TEST(UsingExternalAsciiString) { new TestAsciiResource(i::StrDup(one_byte_string))); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); // Trigger GCs so that the newly allocated string moves to old gen. - i::Heap::CollectGarbage(i::NEW_SPACE); // in survivor space now - i::Heap::CollectGarbage(i::NEW_SPACE); // in old gen now - i::Handle<i::String> isymbol = i::Factory::SymbolFromString(istring); + HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now + HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now + i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - i::Heap::CollectAllGarbage(false); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } @@ -603,12 +613,12 @@ THREADED_TEST(ScavengeExternalString) { Local<String> string = String::NewExternal(new TestResource(two_byte_string)); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); - i::Heap::CollectGarbage(i::NEW_SPACE); - in_new_space = i::Heap::InNewSpace(*istring); - CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring)); + HEAP->CollectGarbage(i::NEW_SPACE); + in_new_space = HEAP->InNewSpace(*istring); + CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring)); CHECK_EQ(0, TestResource::dispose_count); } - i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); + HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); CHECK_EQ(1, TestResource::dispose_count); } @@ -622,12 +632,12 @@ THREADED_TEST(ScavengeExternalAsciiString) { Local<String> string = String::NewExternal( new TestAsciiResource(i::StrDup(one_byte_string))); i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); - i::Heap::CollectGarbage(i::NEW_SPACE); - in_new_space = i::Heap::InNewSpace(*istring); - CHECK(in_new_space || i::Heap::old_data_space()->Contains(*istring)); + HEAP->CollectGarbage(i::NEW_SPACE); + in_new_space = HEAP->InNewSpace(*istring); + CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring)); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::Heap::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); + HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE); CHECK_EQ(1, TestAsciiResource::dispose_count); } @@ -667,11 +677,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(0, TestAsciiResource::dispose_count); @@ -688,11 +698,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(0, TestAsciiResource::dispose_count); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(1, TestAsciiResource::dispose_count); } @@ -738,9 +748,9 @@ THREADED_TEST(StringConcat) { CHECK(value->IsNumber()); CHECK_EQ(68, value->Int32Value()); } - i::CompilationCache::Clear(); - i::Heap::CollectAllGarbage(false); - i::Heap::CollectAllGarbage(false); + i::Isolate::Current()->compilation_cache()->Clear(); + HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } @@ -1041,8 +1051,10 @@ THREADED_TEST(Date) { v8::HandleScope scope; LocalContext env; double PI = 3.1415926; - Local<Value> date_obj = v8::Date::New(PI); - CHECK_EQ(3.0, date_obj->NumberValue()); + Local<Value> date = v8::Date::New(PI); + CHECK_EQ(3.0, date->NumberValue()); + date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42)); + CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value()); } @@ -1575,12 +1587,12 @@ THREADED_TEST(InternalFieldsNativePointers) { // Check reading and writing aligned pointers. obj->SetPointerInInternalField(0, aligned); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); // Check reading and writing unaligned pointers. obj->SetPointerInInternalField(0, unaligned); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1606,19 +1618,19 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) { CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); obj->SetPointerInInternalField(0, aligned); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetPointerInInternalField(0, unaligned); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetInternalField(0, v8::External::Wrap(aligned)); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); obj->SetInternalField(0, v8::External::Wrap(unaligned)); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1631,7 +1643,7 @@ THREADED_TEST(IdentityHash) { // Ensure that the test starts with an fresh heap to test whether the hash // code is based on the address. - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); Local<v8::Object> obj = v8::Object::New(); int hash = obj->GetIdentityHash(); int hash1 = obj->GetIdentityHash(); @@ -1641,7 +1653,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); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); 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 @@ -1678,7 +1690,7 @@ THREADED_TEST(HiddenProperties) { v8::Local<v8::String> empty = v8_str(""); v8::Local<v8::String> prop_name = v8_str("prop_name"); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); // Make sure delete of a non-existent hidden value works CHECK(obj->DeleteHiddenValue(key)); @@ -1688,7 +1700,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002))); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); // Make sure we do not find the hidden property. CHECK(!obj->Has(empty)); @@ -1699,7 +1711,7 @@ THREADED_TEST(HiddenProperties) { CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); CHECK_EQ(2003, obj->Get(empty)->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); // Add another property and delete it afterwards to force the object in // slow case. @@ -1710,7 +1722,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->Delete(prop_name)); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK(obj->DeleteHiddenValue(key)); CHECK(obj->GetHiddenValue(key).IsEmpty()); @@ -1789,6 +1801,180 @@ THREADED_TEST(GlobalHandle) { } +static int NumberOfWeakCalls = 0; +static void WeakPointerCallback(Persistent<Value> handle, void* id) { + CHECK_EQ(reinterpret_cast<void*>(1234), id); + NumberOfWeakCalls++; + handle.Dispose(); +} + +THREADED_TEST(ApiObjectGroups) { + HandleScope scope; + LocalContext env; + + NumberOfWeakCalls = 0; + + Persistent<Object> g1s1; + Persistent<Object> g1s2; + Persistent<Object> g1c1; + Persistent<Object> g2s1; + Persistent<Object> g2s2; + Persistent<Object> g2c1; + + { + 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); + + 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); + } + + Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. + + // Connect group 1 and 2, make a cycle. + CHECK(g1s2->Set(0, g2s2)); + CHECK(g2s1->Set(0, g1s1)); + + { + Persistent<Value> g1_objects[] = { g1s1, g1s2 }; + Persistent<Value> g1_children[] = { g1c1 }; + Persistent<Value> g2_objects[] = { g2s1, g2s2 }; + Persistent<Value> g2_children[] = { g2c1 }; + V8::AddObjectGroup(g1_objects, 2); + V8::AddImplicitReferences(g1s1, g1_children, 1); + V8::AddObjectGroup(g2_objects, 2); + V8::AddImplicitReferences(g2s2, g2_children, 1); + } + // Do a full GC + HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + + // All object should be alive. + CHECK_EQ(0, NumberOfWeakCalls); + + // Weaken the root. + root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + // But make children strong roots---all the objects (except for children) + // should be collectable now. + g1c1.ClearWeak(); + g2c1.ClearWeak(); + + // Groups are deleted, rebuild groups. + { + Persistent<Value> g1_objects[] = { g1s1, g1s2 }; + Persistent<Value> g1_children[] = { g1c1 }; + Persistent<Value> g2_objects[] = { g2s1, g2s2 }; + Persistent<Value> g2_children[] = { g2c1 }; + V8::AddObjectGroup(g1_objects, 2); + V8::AddImplicitReferences(g1s1, g1_children, 1); + V8::AddObjectGroup(g2_objects, 2); + V8::AddImplicitReferences(g2s2, g2_children, 1); + } + + HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + + // All objects should be gone. 5 global handles in total. + CHECK_EQ(5, NumberOfWeakCalls); + + // And now make children weak again and collect them. + g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + + HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + CHECK_EQ(7, NumberOfWeakCalls); +} + + +THREADED_TEST(ApiObjectGroupsCycle) { + HandleScope scope; + LocalContext env; + + NumberOfWeakCalls = 0; + + Persistent<Object> g1s1; + Persistent<Object> g1s2; + Persistent<Object> g2s1; + Persistent<Object> g2s2; + Persistent<Object> g3s1; + Persistent<Object> g3s2; + + { + 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); + + 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); + + 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); + } + + Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. + + // Connect groups. We're building the following cycle: + // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other + // groups. + { + Persistent<Value> g1_objects[] = { g1s1, g1s2 }; + Persistent<Value> g1_children[] = { g2s1 }; + Persistent<Value> g2_objects[] = { g2s1, g2s2 }; + Persistent<Value> g2_children[] = { g3s1 }; + Persistent<Value> g3_objects[] = { g3s1, g3s2 }; + Persistent<Value> g3_children[] = { g1s1 }; + V8::AddObjectGroup(g1_objects, 2); + V8::AddImplicitReferences(g1s1, g1_children, 1); + V8::AddObjectGroup(g2_objects, 2); + V8::AddImplicitReferences(g2s1, g2_children, 1); + V8::AddObjectGroup(g3_objects, 2); + V8::AddImplicitReferences(g3s1, g3_children, 1); + } + // Do a full GC + HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + + // All object should be alive. + CHECK_EQ(0, NumberOfWeakCalls); + + // Weaken the root. + root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + + // Groups are deleted, rebuild groups. + { + Persistent<Value> g1_objects[] = { g1s1, g1s2 }; + Persistent<Value> g1_children[] = { g2s1 }; + Persistent<Value> g2_objects[] = { g2s1, g2s2 }; + Persistent<Value> g2_children[] = { g3s1 }; + Persistent<Value> g3_objects[] = { g3s1, g3s2 }; + Persistent<Value> g3_children[] = { g1s1 }; + V8::AddObjectGroup(g1_objects, 2); + V8::AddImplicitReferences(g1s1, g1_children, 1); + V8::AddObjectGroup(g2_objects, 2); + V8::AddImplicitReferences(g2s1, g2_children, 1); + V8::AddObjectGroup(g3_objects, 2); + V8::AddImplicitReferences(g3s1, g3_children, 1); + } + + HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + + // All objects should be gone. 7 global handles in total. + CHECK_EQ(7, NumberOfWeakCalls); +} + + THREADED_TEST(ScriptException) { v8::HandleScope scope; LocalContext env; @@ -1900,6 +2086,10 @@ THREADED_TEST(Array) { CHECK_EQ(1, arr->Get(0)->Int32Value()); CHECK_EQ(2, arr->Get(1)->Int32Value()); CHECK_EQ(3, arr->Get(2)->Int32Value()); + array = v8::Array::New(27); + CHECK_EQ(27, array->Length()); + array = v8::Array::New(-27); + CHECK_EQ(0, array->Length()); } @@ -2082,8 +2272,6 @@ TEST(OutOfMemoryNested) { TEST(HugeConsStringOutOfMemory) { // It's not possible to read a snapshot into a heap with different dimensions. if (i::Snapshot::IsEnabled()) return; - v8::HandleScope scope; - LocalContext context; // Set heap limits. static const int K = 1024; v8::ResourceConstraints constraints; @@ -2094,6 +2282,9 @@ TEST(HugeConsStringOutOfMemory) { // Execute a script that causes out of memory. v8::V8::IgnoreOutOfMemoryException(); + v8::HandleScope scope; + LocalContext context; + // Build huge string. This should fail with out of memory exception. Local<Value> result = CompileRun( "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();" @@ -2473,6 +2664,21 @@ TEST(APIThrowMessageAndVerboseTryCatch) { } +TEST(APIStackOverflowAndVerboseTryCatch) { + message_received = false; + v8::HandleScope scope; + v8::V8::AddMessageListener(receive_message); + LocalContext context; + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + Local<Value> result = CompileRun("function foo() { foo(); } foo();"); + CHECK(try_catch.HasCaught()); + CHECK(result.IsEmpty()); + CHECK(message_received); + v8::V8::RemoveMessageListeners(receive_message); +} + + THREADED_TEST(ExternalScriptException) { v8::HandleScope scope; Local<ObjectTemplate> templ = ObjectTemplate::New(); @@ -2513,7 +2719,7 @@ v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) { if (try_catch.HasCaught()) { CHECK_EQ(expected, count); CHECK(result.IsEmpty()); - CHECK(!i::Top::has_scheduled_exception()); + CHECK(!i::Isolate::Current()->has_scheduled_exception()); } else { CHECK_NE(expected, count); } @@ -2833,8 +3039,7 @@ THREADED_TEST(DefinePropertyOnAPIAccessor) { result = script_define->Run(); CHECK(try_catch.HasCaught()); String::AsciiValue exception_value(try_catch.Exception()); - CHECK_EQ(*exception_value, - "TypeError: Cannot redefine property: defineProperty"); + CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x"); } THREADED_TEST(DefinePropertyOnDefineGetterSetter) { @@ -2879,8 +3084,7 @@ THREADED_TEST(DefinePropertyOnDefineGetterSetter) { result = script_define->Run(); CHECK(try_catch.HasCaught()); String::AsciiValue exception_value(try_catch.Exception()); - CHECK_EQ(*exception_value, - "TypeError: Cannot redefine property: defineProperty"); + CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x"); } @@ -2998,8 +3202,7 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) { "{get: function() { return 'func'; }})"); CHECK(try_catch.HasCaught()); String::AsciiValue exception_value(try_catch.Exception()); - CHECK_EQ(*exception_value, - "TypeError: Cannot redefine property: defineProperty"); + CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x"); } { v8::TryCatch try_catch; @@ -3007,8 +3210,7 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) { "{get: function() { return 'func'; }})"); CHECK(try_catch.HasCaught()); String::AsciiValue exception_value(try_catch.Exception()); - CHECK_EQ(*exception_value, - "TypeError: Cannot redefine property: defineProperty"); + CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x"); } } @@ -3660,6 +3862,49 @@ THREADED_TEST(UndetectableObject) { } +THREADED_TEST(VoidLiteral) { + v8::HandleScope scope; + LocalContext env; + + Local<v8::FunctionTemplate> desc = + v8::FunctionTemplate::New(0, v8::Handle<Value>()); + desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable + + Local<v8::Object> obj = desc->GetFunction()->NewInstance(); + env->Global()->Set(v8_str("undetectable"), obj); + + ExpectBoolean("undefined == void 0", true); + ExpectBoolean("undetectable == void 0", true); + ExpectBoolean("null == void 0", true); + ExpectBoolean("undefined === void 0", true); + ExpectBoolean("undetectable === void 0", false); + ExpectBoolean("null === void 0", false); + + ExpectBoolean("void 0 == undefined", true); + ExpectBoolean("void 0 == undetectable", true); + ExpectBoolean("void 0 == null", true); + ExpectBoolean("void 0 === undefined", true); + ExpectBoolean("void 0 === undetectable", false); + ExpectBoolean("void 0 === null", false); + + ExpectString("(function() {" + " try {" + " return x === void 0;" + " } catch(e) {" + " return e.toString();" + " }" + "})()", + "ReferenceError: x is not defined"); + ExpectString("(function() {" + " try {" + " return void 0 === x;" + " } catch(e) {" + " return e.toString();" + " }" + "})()", + "ReferenceError: x is not defined"); +} + THREADED_TEST(ExtensibleOnUndetectable) { v8::HandleScope scope; @@ -3688,10 +3933,8 @@ THREADED_TEST(ExtensibleOnUndetectable) { source = v8_str("undetectable.y = 2000;"); script = Script::Compile(source); - v8::TryCatch try_catch; Local<Value> result = script->Run(); - CHECK(result.IsEmpty()); - CHECK(try_catch.HasCaught()); + ExpectBoolean("undetectable.y == undefined", true); } @@ -3736,6 +3979,38 @@ THREADED_TEST(UndetectableString) { } +TEST(UndetectableOptimized) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope; + LocalContext env; + + Local<String> obj = String::NewUndetectable("foo"); + env->Global()->Set(v8_str("undetectable"), obj); + env->Global()->Set(v8_str("detectable"), v8_str("bar")); + + ExpectString( + "function testBranch() {" + " if (!%_IsUndetectableObject(undetectable)) throw 1;" + " if (%_IsUndetectableObject(detectable)) throw 2;" + "}\n" + "function testBool() {" + " var b1 = !%_IsUndetectableObject(undetectable);" + " var b2 = %_IsUndetectableObject(detectable);" + " if (b1) throw 3;" + " if (b2) throw 4;" + " return b1 == b2;" + "}\n" + "%OptimizeFunctionOnNextCall(testBranch);" + "%OptimizeFunctionOnNextCall(testBool);" + "for (var i = 0; i < 10; i++) {" + " testBranch();" + " testBool();" + "}\n" + "\"PASS\"", + "PASS"); +} + + template <typename T> static void USE(T) { } @@ -3925,6 +4200,69 @@ THREADED_TEST(NativeCallInExtensions) { } +class NativeFunctionExtension : public Extension { + public: + NativeFunctionExtension(const char* name, + const char* source, + v8::InvocationCallback fun = &Echo) + : Extension(name, source), + function_(fun) { } + + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + v8::Handle<v8::String> name) { + return v8::FunctionTemplate::New(function_); + } + + static v8::Handle<v8::Value> Echo(const v8::Arguments& args) { + if (args.Length() >= 1) return (args[0]); + return v8::Undefined(); + } + private: + v8::InvocationCallback function_; +}; + + +THREADED_TEST(NativeFunctionDeclaration) { + v8::HandleScope handle_scope; + const char* name = "nativedecl"; + v8::RegisterExtension(new NativeFunctionExtension(name, + "native function foo();")); + const char* extension_names[] = { name }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + Context::Scope lock(context); + v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run(); + CHECK_EQ(result, v8::Integer::New(42)); +} + + +THREADED_TEST(NativeFunctionDeclarationError) { + v8::HandleScope handle_scope; + const char* name = "nativedeclerr"; + // Syntax error in extension code. + v8::RegisterExtension(new NativeFunctionExtension(name, + "native\nfunction foo();")); + const char* extension_names[] = { name }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + ASSERT(context.IsEmpty()); +} + +THREADED_TEST(NativeFunctionDeclarationErrorEscape) { + v8::HandleScope handle_scope; + const char* name = "nativedeclerresc"; + // Syntax error in extension code - escape code in "native" means that + // it's not treated as a keyword. + v8::RegisterExtension(new NativeFunctionExtension( + name, + "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()); +} + + static void CheckDependencies(const char* name, const char* expected) { v8::HandleScope handle_scope; v8::ExtensionConfiguration config(1, &name); @@ -4196,55 +4534,116 @@ THREADED_TEST(WeakReference) { } -static bool in_scavenge = false; -static int last = -1; - -static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { - CHECK_EQ(-1, last); - last = 0; +static void DisposeAndSetFlag(v8::Persistent<v8::Value> obj, void* data) { obj.Dispose(); obj.Clear(); - in_scavenge = true; - i::Heap::PerformScavenge(); - in_scavenge = false; *(reinterpret_cast<bool*>(data)) = true; } -static void CheckIsNotInvokedInScavenge(v8::Persistent<v8::Value> obj, - void* data) { - CHECK_EQ(0, last); - last = 1; - *(reinterpret_cast<bool*>(data)) = in_scavenge; - obj.Dispose(); - obj.Clear(); -} -THREADED_TEST(NoWeakRefCallbacksInScavenge) { - // Test verifies that scavenge cannot invoke WeakReferenceCallbacks. - // Calling callbacks from scavenges is unsafe as objects held by those - // handlers might have become strongly reachable, but scavenge doesn't - // check that. +THREADED_TEST(IndependentWeakHandle) { v8::Persistent<Context> context = Context::New(); Context::Scope context_scope(context); v8::Persistent<v8::Object> object_a; - v8::Persistent<v8::Object> object_b; { v8::HandleScope handle_scope; - object_b = v8::Persistent<v8::Object>::New(v8::Object::New()); object_a = v8::Persistent<v8::Object>::New(v8::Object::New()); } bool object_a_disposed = false; - object_a.MakeWeak(&object_a_disposed, &ForceScavenge); - bool released_in_scavenge = false; - object_b.MakeWeak(&released_in_scavenge, &CheckIsNotInvokedInScavenge); + object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag); + object_a.MarkIndependent(); + HEAP->PerformScavenge(); + CHECK(object_a_disposed); +} + + +static void InvokeScavenge() { + HEAP->PerformScavenge(); +} + + +static void InvokeMarkSweep() { + HEAP->CollectAllGarbage(false); +} + + +static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { + obj.Dispose(); + obj.Clear(); + *(reinterpret_cast<bool*>(data)) = true; + InvokeScavenge(); +} + + +static void ForceMarkSweep(v8::Persistent<v8::Value> obj, void* data) { + obj.Dispose(); + obj.Clear(); + *(reinterpret_cast<bool*>(data)) = true; + InvokeMarkSweep(); +} + + +THREADED_TEST(GCFromWeakCallbacks) { + v8::Persistent<Context> context = Context::New(); + Context::Scope context_scope(context); + + static const int kNumberOfGCTypes = 2; + v8::WeakReferenceCallback gc_forcing_callback[kNumberOfGCTypes] = + {&ForceScavenge, &ForceMarkSweep}; - while (!object_a_disposed) { - i::Heap::CollectAllGarbage(false); + typedef void (*GCInvoker)(); + GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; + + for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { + for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { + v8::Persistent<v8::Object> object; + { + v8::HandleScope handle_scope; + object = v8::Persistent<v8::Object>::New(v8::Object::New()); + } + bool disposed = false; + object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]); + object.MarkIndependent(); + invoke_gc[outer_gc](); + CHECK(disposed); + } + } +} + + +static void RevivingCallback(v8::Persistent<v8::Value> obj, void* data) { + obj.ClearWeak(); + *(reinterpret_cast<bool*>(data)) = true; +} + + +THREADED_TEST(IndependentHandleRevival) { + v8::Persistent<Context> context = Context::New(); + Context::Scope context_scope(context); + + v8::Persistent<v8::Object> object; + { + v8::HandleScope handle_scope; + object = v8::Persistent<v8::Object>::New(v8::Object::New()); + object->Set(v8_str("x"), v8::Integer::New(1)); + v8::Local<String> y_str = v8_str("y"); + object->Set(y_str, y_str); + } + bool revived = false; + object.MakeWeak(&revived, &RevivingCallback); + object.MarkIndependent(); + HEAP->PerformScavenge(); + CHECK(revived); + HEAP->CollectAllGarbage(true); + { + v8::HandleScope handle_scope; + v8::Local<String> y_str = v8_str("y"); + CHECK_EQ(v8::Integer::New(1), object->Get(v8_str("x"))); + CHECK(object->Get(y_str)->Equals(y_str)); } - CHECK(!released_in_scavenge); } @@ -4260,7 +4659,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; - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); return v8::Undefined(); } @@ -4562,130 +4961,130 @@ THREADED_TEST(StringWrite) { memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen); - CHECK_EQ(len, 9); - CHECK_EQ(charlen, 5); - CHECK_EQ(strcmp(utf8buf, "abc\303\260\342\230\203"), 0); + CHECK_EQ(9, len); + CHECK_EQ(5, charlen); + CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203")); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 8, &charlen); - CHECK_EQ(len, 8); - CHECK_EQ(charlen, 5); - CHECK_EQ(strncmp(utf8buf, "abc\303\260\342\230\203\1", 9), 0); + 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)); len = str2->WriteUtf8(utf8buf, 7, &charlen); - CHECK_EQ(len, 5); - CHECK_EQ(charlen, 4); - CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0); + CHECK_EQ(5, len); + CHECK_EQ(4, charlen); + CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 6, &charlen); - CHECK_EQ(len, 5); - CHECK_EQ(charlen, 4); - CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0); + CHECK_EQ(5, len); + CHECK_EQ(4, charlen); + CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 5, &charlen); - CHECK_EQ(len, 5); - CHECK_EQ(charlen, 4); - CHECK_EQ(strncmp(utf8buf, "abc\303\260\1", 5), 0); + CHECK_EQ(5, len); + CHECK_EQ(4, charlen); + CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 4, &charlen); - CHECK_EQ(len, 3); - CHECK_EQ(charlen, 3); - CHECK_EQ(strncmp(utf8buf, "abc\1", 4), 0); + CHECK_EQ(3, len); + CHECK_EQ(3, charlen); + CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 3, &charlen); - CHECK_EQ(len, 3); - CHECK_EQ(charlen, 3); - CHECK_EQ(strncmp(utf8buf, "abc\1", 4), 0); + CHECK_EQ(3, len); + CHECK_EQ(3, charlen); + CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); memset(utf8buf, 0x1, sizeof(utf8buf)); len = str2->WriteUtf8(utf8buf, 2, &charlen); - CHECK_EQ(len, 2); - CHECK_EQ(charlen, 2); - CHECK_EQ(strncmp(utf8buf, "ab\1", 3), 0); + CHECK_EQ(2, len); + CHECK_EQ(2, charlen); + CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf); - CHECK_EQ(len, 5); + CHECK_EQ(5, len); len = str->Write(wbuf); - CHECK_EQ(len, 5); - CHECK_EQ(strcmp("abcde", buf), 0); + CHECK_EQ(5, len); + CHECK_EQ(0, strcmp("abcde", buf)); uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'}; - CHECK_EQ(StrCmp16(answer1, wbuf), 0); + CHECK_EQ(0, StrCmp16(answer1, wbuf)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 0, 4); - CHECK_EQ(len, 4); + CHECK_EQ(4, len); len = str->Write(wbuf, 0, 4); - CHECK_EQ(len, 4); - CHECK_EQ(strncmp("abcd\1", buf, 5), 0); + CHECK_EQ(4, len); + CHECK_EQ(0, strncmp("abcd\1", buf, 5)); uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101}; - CHECK_EQ(StrNCmp16(answer2, wbuf, 5), 0); + CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 0, 5); - CHECK_EQ(len, 5); + CHECK_EQ(5, len); len = str->Write(wbuf, 0, 5); - CHECK_EQ(len, 5); - CHECK_EQ(strncmp("abcde\1", buf, 6), 0); + CHECK_EQ(5, len); + CHECK_EQ(0, strncmp("abcde\1", buf, 6)); uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101}; - CHECK_EQ(StrNCmp16(answer3, wbuf, 6), 0); + CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 0, 6); - CHECK_EQ(len, 5); + CHECK_EQ(5, len); len = str->Write(wbuf, 0, 6); - CHECK_EQ(len, 5); - CHECK_EQ(strcmp("abcde", buf), 0); + CHECK_EQ(5, len); + CHECK_EQ(0, strcmp("abcde", buf)); uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'}; - CHECK_EQ(StrCmp16(answer4, wbuf), 0); + CHECK_EQ(0, StrCmp16(answer4, wbuf)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 4, -1); - CHECK_EQ(len, 1); + CHECK_EQ(1, len); len = str->Write(wbuf, 4, -1); - CHECK_EQ(len, 1); - CHECK_EQ(strcmp("e", buf), 0); + CHECK_EQ(1, len); + CHECK_EQ(0, strcmp("e", buf)); uint16_t answer5[] = {'e', '\0'}; - CHECK_EQ(StrCmp16(answer5, wbuf), 0); + CHECK_EQ(0, StrCmp16(answer5, wbuf)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 4, 6); - CHECK_EQ(len, 1); + CHECK_EQ(1, len); len = str->Write(wbuf, 4, 6); - CHECK_EQ(len, 1); - CHECK_EQ(strcmp("e", buf), 0); - CHECK_EQ(StrCmp16(answer5, wbuf), 0); + CHECK_EQ(1, len); + CHECK_EQ(0, strcmp("e", buf)); + CHECK_EQ(0, StrCmp16(answer5, wbuf)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 4, 1); - CHECK_EQ(len, 1); + CHECK_EQ(1, len); len = str->Write(wbuf, 4, 1); - CHECK_EQ(len, 1); - CHECK_EQ(strncmp("e\1", buf, 2), 0); + CHECK_EQ(1, len); + CHECK_EQ(0, strncmp("e\1", buf, 2)); uint16_t answer6[] = {'e', 0x101}; - CHECK_EQ(StrNCmp16(answer6, wbuf, 2), 0); + CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2)); memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf, 3, 1); - CHECK_EQ(len, 1); + CHECK_EQ(1, len); len = str->Write(wbuf, 3, 1); - CHECK_EQ(len, 1); - CHECK_EQ(strncmp("d\1", buf, 2), 0); + CHECK_EQ(1, len); + CHECK_EQ(0, strncmp("d\1", buf, 2)); uint16_t answer7[] = {'d', 0x101}; - CHECK_EQ(StrNCmp16(answer7, wbuf, 2), 0); + CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2)); } @@ -5659,6 +6058,14 @@ TEST(AccessControlES5) { global_template->SetAccessCheckCallbacks(NamedAccessBlocker, IndexedAccessBlocker); + // Add accessible accessor. + global_template->SetAccessor( + v8_str("accessible_prop"), + EchoGetter, EchoSetter, + v8::Handle<Value>(), + v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE)); + + // Add an accessor that is not accessible by cross-domain JS code. global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter, UnreachableSetter, @@ -5699,6 +6106,18 @@ TEST(AccessControlES5) { CompileRun("Object.seal(other)"); ExpectTrue("Object.isExtensible(other)"); + + // Regression test for issue 1250. + // Make sure that we can set the accessible accessors value using normal + // assignment. + CompileRun("other.accessible_prop = 42"); + CHECK_EQ(42, g_echo_value); + + v8::Handle<Value> value; + // We follow Safari in ignoring assignments to host object accessors. + CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})"); + value = CompileRun("other.accessible_prop == 42"); + CHECK(value->IsTrue()); } @@ -6347,7 +6766,7 @@ THREADED_TEST(ShadowObject) { context->Global()->Set(v8_str("__proto__"), o); Local<Value> value = - Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run(); + Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run(); CHECK(value->IsBoolean()); CHECK(!value->BooleanValue()); @@ -6466,6 +6885,56 @@ THREADED_TEST(SetPrototype) { } +THREADED_TEST(SetPrototypeProperties) { + v8::HandleScope handle_scope; + LocalContext context; + + Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(); + t1->SetPrototypeAttributes(v8::DontDelete); + context->Global()->Set(v8_str("func1"), t1->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');" + " return (descriptor['writable'] == true) &&" + " (descriptor['enumerable'] == true) &&" + " (descriptor['configurable'] == false);" + "})()")->BooleanValue()); + + Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(); + t2->SetPrototypeAttributes(v8::DontEnum); + context->Global()->Set(v8_str("func2"), t2->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');" + " return (descriptor['writable'] == true) &&" + " (descriptor['enumerable'] == false) &&" + " (descriptor['configurable'] == true);" + "})()")->BooleanValue()); + + Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(); + t3->SetPrototypeAttributes(v8::ReadOnly); + context->Global()->Set(v8_str("func3"), t3->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func3, 'prototype');" + " return (descriptor['writable'] == false) &&" + " (descriptor['enumerable'] == true) &&" + " (descriptor['configurable'] == true);" + "})()")->BooleanValue()); + + Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(); + t4->SetPrototypeAttributes(v8::ReadOnly | v8::DontEnum | v8::DontDelete); + context->Global()->Set(v8_str("func4"), t4->GetFunction()); + CHECK(CompileRun( + "(function() {" + " descriptor = Object.getOwnPropertyDescriptor(func4, 'prototype');" + " return (descriptor['writable'] == false) &&" + " (descriptor['enumerable'] == false) &&" + " (descriptor['configurable'] == false);" + "})()")->BooleanValue()); +} + + THREADED_TEST(SetPrototypeThrows) { v8::HandleScope handle_scope; LocalContext context; @@ -6481,7 +6950,7 @@ THREADED_TEST(SetPrototypeThrows) { v8::TryCatch try_catch; CHECK(!o1->SetPrototype(o0)); CHECK(!try_catch.HasCaught()); - ASSERT(!i::Top::has_pending_exception()); + ASSERT(!i::Isolate::Current()->has_pending_exception()); CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value()); } @@ -6523,6 +6992,200 @@ THREADED_TEST(Constructor) { CHECK(value->BooleanValue()); } + +static Handle<Value> ConstructorCallback(const Arguments& args) { + ApiTestFuzzer::Fuzz(); + Local<Object> This; + + if (args.IsConstructCall()) { + Local<Object> Holder = args.Holder(); + This = Object::New(); + Local<Value> proto = Holder->GetPrototype(); + if (proto->IsObject()) { + This->SetPrototype(proto); + } + } else { + This = args.This(); + } + + This->Set(v8_str("a"), args[0]); + return This; +} + + +static Handle<Value> FakeConstructorCallback(const Arguments& args) { + ApiTestFuzzer::Fuzz(); + return args[0]; +} + + +THREADED_TEST(ConstructorForObject) { + v8::HandleScope handle_scope; + LocalContext context; + + { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + instance_template->SetCallAsFunctionHandler(ConstructorCallback); + Local<Object> instance = instance_template->NewInstance(); + context->Global()->Set(v8_str("obj"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + // Call the Object's constructor with a 32-bit signed integer. + value = CompileRun("(function() { var o = new obj(28); return o.a; })()"); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsInt32()); + CHECK_EQ(28, value->Int32Value()); + + Local<Value> args1[] = { v8_num(28) }; + Local<Value> value_obj1 = instance->CallAsConstructor(1, args1); + CHECK(value_obj1->IsObject()); + Local<Object> object1 = Local<Object>::Cast(value_obj1); + value = object1->Get(v8_str("a")); + CHECK(value->IsInt32()); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(28, value->Int32Value()); + + // Call the Object's constructor with a String. + value = CompileRun( + "(function() { var o = new obj('tipli'); return o.a; })()"); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsString()); + String::AsciiValue string_value1(value->ToString()); + CHECK_EQ("tipli", *string_value1); + + Local<Value> args2[] = { v8_str("tipli") }; + Local<Value> value_obj2 = instance->CallAsConstructor(1, args2); + CHECK(value_obj2->IsObject()); + Local<Object> object2 = Local<Object>::Cast(value_obj2); + value = object2->Get(v8_str("a")); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsString()); + String::AsciiValue string_value2(value->ToString()); + CHECK_EQ("tipli", *string_value2); + + // Call the Object's constructor with a Boolean. + value = CompileRun("(function() { var o = new obj(true); return o.a; })()"); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsBoolean()); + CHECK_EQ(true, value->BooleanValue()); + + Handle<Value> args3[] = { v8::Boolean::New(true) }; + Local<Value> value_obj3 = instance->CallAsConstructor(1, args3); + CHECK(value_obj3->IsObject()); + Local<Object> object3 = Local<Object>::Cast(value_obj3); + value = object3->Get(v8_str("a")); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsBoolean()); + CHECK_EQ(true, value->BooleanValue()); + + // Call the Object's constructor with undefined. + Handle<Value> args4[] = { v8::Undefined() }; + Local<Value> value_obj4 = instance->CallAsConstructor(1, args4); + CHECK(value_obj4->IsObject()); + Local<Object> object4 = Local<Object>::Cast(value_obj4); + value = object4->Get(v8_str("a")); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsUndefined()); + + // Call the Object's constructor with null. + Handle<Value> args5[] = { v8::Null() }; + Local<Value> value_obj5 = instance->CallAsConstructor(1, args5); + CHECK(value_obj5->IsObject()); + Local<Object> object5 = Local<Object>::Cast(value_obj5); + value = object5->Get(v8_str("a")); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsNull()); + } + + // Check exception handling when there is no constructor set for the Object. + { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + Local<Object> instance = instance_template->NewInstance(); + context->Global()->Set(v8_str("obj2"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + value = CompileRun("new obj2(28)"); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value1(try_catch.Exception()); + CHECK_EQ("TypeError: object is not a function", *exception_value1); + try_catch.Reset(); + + Local<Value> args[] = { v8_num(29) }; + value = instance->CallAsConstructor(1, args); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value2(try_catch.Exception()); + CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2); + try_catch.Reset(); + } + + // Check the case when constructor throws exception. + { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + instance_template->SetCallAsFunctionHandler(ThrowValue); + Local<Object> instance = instance_template->NewInstance(); + context->Global()->Set(v8_str("obj3"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + value = CompileRun("new obj3(22)"); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value1(try_catch.Exception()); + CHECK_EQ("22", *exception_value1); + try_catch.Reset(); + + Local<Value> args[] = { v8_num(23) }; + value = instance->CallAsConstructor(1, args); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value2(try_catch.Exception()); + CHECK_EQ("23", *exception_value2); + try_catch.Reset(); + } + + // Check whether constructor returns with an object or non-object. + { Local<FunctionTemplate> function_template = + FunctionTemplate::New(FakeConstructorCallback); + Local<Function> function = function_template->GetFunction(); + Local<Object> instance1 = function; + context->Global()->Set(v8_str("obj4"), instance1); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + CHECK(instance1->IsObject()); + CHECK(instance1->IsFunction()); + + value = CompileRun("new obj4(28)"); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsObject()); + + Local<Value> args1[] = { v8_num(28) }; + value = instance1->CallAsConstructor(1, args1); + CHECK(!try_catch.HasCaught()); + CHECK(value->IsObject()); + + Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); + Local<Object> instance2 = instance_template->NewInstance(); + context->Global()->Set(v8_str("obj5"), instance2); + CHECK(!try_catch.HasCaught()); + + CHECK(instance2->IsObject()); + CHECK(!instance2->IsFunction()); + + value = CompileRun("new obj5(28)"); + CHECK(!try_catch.HasCaught()); + CHECK(!value->IsObject()); + + Local<Value> args2[] = { v8_num(28) }; + value = instance2->CallAsConstructor(1, args2); + CHECK(!try_catch.HasCaught()); + CHECK(!value->IsObject()); + } +} + + THREADED_TEST(FunctionDescriptorException) { v8::HandleScope handle_scope; LocalContext context; @@ -6739,50 +7402,153 @@ THREADED_TEST(CallAsFunction) { v8::HandleScope scope; LocalContext context; - Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); - Local<ObjectTemplate> instance_template = t->InstanceTemplate(); - instance_template->SetCallAsFunctionHandler(call_as_function); - Local<v8::Object> instance = t->GetFunction()->NewInstance(); - context->Global()->Set(v8_str("obj"), instance); - v8::TryCatch try_catch; - Local<Value> value; - CHECK(!try_catch.HasCaught()); + { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); + Local<ObjectTemplate> instance_template = t->InstanceTemplate(); + instance_template->SetCallAsFunctionHandler(call_as_function); + Local<v8::Object> instance = t->GetFunction()->NewInstance(); + context->Global()->Set(v8_str("obj"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); - value = CompileRun("obj(42)"); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(42, value->Int32Value()); + value = CompileRun("obj(42)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(42, value->Int32Value()); - value = CompileRun("(function(o){return o(49)})(obj)"); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(49, value->Int32Value()); + value = CompileRun("(function(o){return o(49)})(obj)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(49, value->Int32Value()); - // test special case of call as function - value = CompileRun("[obj]['0'](45)"); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(45, value->Int32Value()); + // test special case of call as function + value = CompileRun("[obj]['0'](45)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(45, value->Int32Value()); - value = CompileRun("obj.call = Function.prototype.call;" - "obj.call(null, 87)"); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(87, value->Int32Value()); + value = CompileRun("obj.call = Function.prototype.call;" + "obj.call(null, 87)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(87, value->Int32Value()); - // Regression tests for bug #1116356: Calling call through call/apply - // must work for non-function receivers. - const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; - value = CompileRun(apply_99); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(99, value->Int32Value()); + // Regression tests for bug #1116356: Calling call through call/apply + // must work for non-function receivers. + const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; + value = CompileRun(apply_99); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(99, value->Int32Value()); - const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; - value = CompileRun(call_17); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(17, value->Int32Value()); + const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; + value = CompileRun(call_17); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(17, value->Int32Value()); - // Check that the call-as-function handler can be called through - // new. - value = CompileRun("new obj(43)"); - CHECK(!try_catch.HasCaught()); - CHECK_EQ(-43, value->Int32Value()); + // Check that the call-as-function handler can be called through + // new. + value = CompileRun("new obj(43)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(-43, value->Int32Value()); + + // Check that the call-as-function handler can be called through + // the API. + v8::Handle<Value> args[] = { v8_num(28) }; + value = instance->CallAsFunction(instance, 1, args); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(28, value->Int32Value()); + } + + { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); + Local<ObjectTemplate> instance_template = t->InstanceTemplate(); + Local<v8::Object> instance = t->GetFunction()->NewInstance(); + context->Global()->Set(v8_str("obj2"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + // Call an object without call-as-function handler through the JS + value = CompileRun("obj2(28)"); + CHECK(value.IsEmpty()); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value1(try_catch.Exception()); + CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function", + *exception_value1); + try_catch.Reset(); + + // Call an object without call-as-function handler through the API + value = CompileRun("obj2(28)"); + v8::Handle<Value> args[] = { v8_num(28) }; + value = instance->CallAsFunction(instance, 1, args); + CHECK(value.IsEmpty()); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value2(try_catch.Exception()); + CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2); + try_catch.Reset(); + } + + { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); + Local<ObjectTemplate> instance_template = t->InstanceTemplate(); + instance_template->SetCallAsFunctionHandler(ThrowValue); + Local<v8::Object> instance = t->GetFunction()->NewInstance(); + context->Global()->Set(v8_str("obj3"), instance); + v8::TryCatch try_catch; + Local<Value> value; + CHECK(!try_catch.HasCaught()); + + // Catch the exception which is thrown by call-as-function handler + value = CompileRun("obj3(22)"); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value1(try_catch.Exception()); + CHECK_EQ("22", *exception_value1); + try_catch.Reset(); + + v8::Handle<Value> args[] = { v8_num(23) }; + value = instance->CallAsFunction(instance, 1, args); + CHECK(try_catch.HasCaught()); + String::AsciiValue exception_value2(try_catch.Exception()); + CHECK_EQ("23", *exception_value2); + try_catch.Reset(); + } +} + + +// Check whether a non-function object is callable. +THREADED_TEST(CallableObject) { + v8::HandleScope scope; + LocalContext context; + + { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + instance_template->SetCallAsFunctionHandler(call_as_function); + Local<Object> instance = instance_template->NewInstance(); + v8::TryCatch try_catch; + + CHECK(instance->IsCallable()); + CHECK(!try_catch.HasCaught()); + } + + { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); + Local<Object> instance = instance_template->NewInstance(); + v8::TryCatch try_catch; + + CHECK(!instance->IsCallable()); + CHECK(!try_catch.HasCaught()); + } + + { Local<FunctionTemplate> function_template = + FunctionTemplate::New(call_as_function); + Local<Function> function = function_template->GetFunction(); + Local<Object> instance = function; + v8::TryCatch try_catch; + + CHECK(instance->IsCallable()); + CHECK(!try_catch.HasCaught()); + } + + { Local<FunctionTemplate> function_template = FunctionTemplate::New(); + Local<Function> function = function_template->GetFunction(); + Local<Object> instance = function; + v8::TryCatch try_catch; + + CHECK(instance->IsCallable()); + CHECK(!try_catch.HasCaught()); + } } @@ -6863,7 +7629,7 @@ static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( Local<String> name, const AccessorInfo& info) { ApiTestFuzzer::Fuzz(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); return v8::Handle<Value>(); } @@ -7593,7 +8359,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) { - i::Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); } return v8::Handle<Value>(); } @@ -7631,7 +8397,7 @@ static void GenerateSomeGarbage() { v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) { static int count = 0; if (count++ % 3 == 0) { - i::Heap::CollectAllGarbage(true); // This should move the stub + HEAP-> CollectAllGarbage(true); // This should move the stub GenerateSomeGarbage(); // This should ensure the old stub memory is flushed } return v8::Handle<v8::Value>(); @@ -7686,7 +8452,7 @@ THREADED_TEST(CallICFastApi_DirectCall_Throw) { v8::Handle<v8::Value> DirectGetterCallback(Local<String> name, const v8::AccessorInfo& info) { if (++p_getter_count % 3 == 0) { - i::Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); GenerateSomeGarbage(); } return v8::Handle<v8::Value>(); @@ -8374,6 +9140,134 @@ THREADED_TEST(NamedPropertyHandlerGetterAttributes) { } +static Handle<Value> ThrowingGetter(Local<String> name, + const AccessorInfo& info) { + ApiTestFuzzer::Fuzz(); + ThrowException(Handle<Value>()); + return Undefined(); +} + + +THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) { + HandleScope scope; + LocalContext context; + + Local<FunctionTemplate> templ = FunctionTemplate::New(); + Local<ObjectTemplate> instance_templ = templ->InstanceTemplate(); + instance_templ->SetAccessor(v8_str("f"), ThrowingGetter); + + Local<Object> instance = templ->GetFunction()->NewInstance(); + + Local<Object> another = Object::New(); + another->SetPrototype(instance); + + Local<Object> with_js_getter = CompileRun( + "o = {};\n" + "o.__defineGetter__('f', function() { throw undefined; });\n" + "o\n").As<Object>(); + CHECK(!with_js_getter.IsEmpty()); + + TryCatch try_catch; + + Local<Value> result = instance->GetRealNamedProperty(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); + + result = another->GetRealNamedProperty(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); + + result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); + + result = another->Get(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); + + result = with_js_getter->GetRealNamedProperty(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); + + result = with_js_getter->Get(v8_str("f")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(result.IsEmpty()); +} + + +static Handle<Value> ThrowingCallbackWithTryCatch(const Arguments& args) { + TryCatch try_catch; + // Verboseness is important: it triggers message delivery which can call into + // external code. + try_catch.SetVerbose(true); + CompileRun("throw 'from JS';"); + CHECK(try_catch.HasCaught()); + CHECK(!i::Isolate::Current()->has_pending_exception()); + CHECK(!i::Isolate::Current()->has_scheduled_exception()); + return Undefined(); +} + + +static int call_depth; + + +static void WithTryCatch(Handle<Message> message, Handle<Value> data) { + TryCatch try_catch; +} + + +static void ThrowFromJS(Handle<Message> message, Handle<Value> data) { + if (--call_depth) CompileRun("throw 'ThrowInJS';"); +} + + +static void ThrowViaApi(Handle<Message> message, Handle<Value> data) { + if (--call_depth) ThrowException(v8_str("ThrowViaApi")); +} + + +static void WebKitLike(Handle<Message> message, Handle<Value> data) { + Handle<String> errorMessageString = message->Get(); + CHECK(!errorMessageString.IsEmpty()); + message->GetStackTrace(); + message->GetScriptResourceName(); +} + +THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) { + HandleScope scope; + LocalContext context; + + Local<Function> func = + FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction(); + context->Global()->Set(v8_str("func"), func); + + MessageCallback callbacks[] = + { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch }; + for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) { + MessageCallback callback = callbacks[i]; + if (callback != NULL) { + V8::AddMessageListener(callback); + } + // Some small number to control number of times message handler should + // throw an exception. + call_depth = 5; + ExpectFalse( + "var thrown = false;\n" + "try { func(); } catch(e) { thrown = true; }\n" + "thrown\n"); + if (callback != NULL) { + V8::RemoveMessageListeners(callback); + } + } +} + + static v8::Handle<Value> ParentGetter(Local<String> name, const AccessorInfo& info) { ApiTestFuzzer::Fuzz(); @@ -8595,11 +9489,10 @@ static unsigned linear_congruential_generator; void ApiTestFuzzer::Setup(PartOfTest part) { linear_congruential_generator = i::FLAG_testing_prng_seed; fuzzing_ = true; - int start = (part == FIRST_PART) ? 0 : (RegisterThreadedTest::count() >> 1); - int end = (part == FIRST_PART) - ? (RegisterThreadedTest::count() >> 1) - : RegisterThreadedTest::count(); - active_tests_ = tests_being_run_ = end - start; + int count = RegisterThreadedTest::count(); + int start = count * part / (LAST_PART + 1); + int end = (count * (part + 1) / (LAST_PART + 1)) - 1; + active_tests_ = tests_being_run_ = end - start + 1; for (int i = 0; i < tests_being_run_; i++) { RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start); } @@ -8668,6 +9561,17 @@ TEST(Threading2) { ApiTestFuzzer::TearDown(); } +TEST(Threading3) { + ApiTestFuzzer::Setup(ApiTestFuzzer::THIRD_PART); + ApiTestFuzzer::RunAllTests(); + ApiTestFuzzer::TearDown(); +} + +TEST(Threading4) { + ApiTestFuzzer::Setup(ApiTestFuzzer::FOURTH_PART); + ApiTestFuzzer::RunAllTests(); + ApiTestFuzzer::TearDown(); +} void ApiTestFuzzer::CallTest() { if (kLogThreading) @@ -8823,11 +9727,12 @@ 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. - i::Heap::CollectAllGarbage(false); - i::Heap::CollectAllGarbage(false); + HEAP->global_context_map(); + HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); int count = GetGlobalObjectsCount(); #ifdef DEBUG - if (count != expected) i::Heap::TracePathToGlobal(); + if (count != expected) HEAP->TracePathToGlobal(); #endif CHECK_EQ(expected, count); } @@ -8893,7 +9798,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) { // weak callback of the first handle would be able to 'reallocate' it. handle1.MakeWeak(NULL, NewPersistentHandleCallback); handle2.Dispose(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } @@ -8901,7 +9806,7 @@ v8::Persistent<v8::Object> to_be_disposed; void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { to_be_disposed.Dispose(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); handle.Dispose(); } @@ -8917,7 +9822,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { } handle1.MakeWeak(NULL, DisposeAndForceGcCallback); to_be_disposed = handle2; - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { @@ -8943,7 +9848,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { } handle2.MakeWeak(NULL, DisposingCallback); handle3.MakeWeak(NULL, HandleCreatingCallback); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); } @@ -9161,6 +10066,19 @@ void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) { } +void CheckOwnProperties(v8::Handle<v8::Value> val, + int elmc, + const char* elmv[]) { + v8::Handle<v8::Object> obj = val.As<v8::Object>(); + v8::Handle<v8::Array> props = obj->GetOwnPropertyNames(); + CHECK_EQ(elmc, props->Length()); + for (int i = 0; i < elmc; i++) { + v8::String::Utf8Value elm(props->Get(v8::Integer::New(i))); + CHECK_EQ(elmv[i], *elm); + } +} + + THREADED_TEST(PropertyEnumeration) { v8::HandleScope scope; LocalContext context; @@ -9178,17 +10096,48 @@ THREADED_TEST(PropertyEnumeration) { int elmc0 = 0; const char** elmv0 = NULL; CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0); + CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0); int elmc1 = 2; const char* elmv1[] = {"a", "b"}; CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); + CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); int elmc2 = 3; const char* elmv2[] = {"0", "1", "2"}; CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); + CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); int elmc3 = 4; const char* elmv3[] = {"w", "z", "x", "y"}; CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3); + int elmc4 = 2; + const char* elmv4[] = {"w", "z"}; + CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4); } +THREADED_TEST(PropertyEnumeration2) { + v8::HandleScope scope; + LocalContext context; + v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New( + "var result = [];" + "result[0] = {};" + "result[1] = {a: 1, b: 2};" + "result[2] = [1, 2, 3];" + "var proto = {x: 1, y: 2, z: 3};" + "var x = { __proto__: proto, w: 0, z: 1 };" + "result[3] = x;" + "result;"))->Run(); + v8::Handle<v8::Array> elms = obj.As<v8::Array>(); + CHECK_EQ(4, elms->Length()); + int elmc0 = 0; + const char** elmv0 = NULL; + CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0); + + v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0)); + v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames(); + CHECK_EQ(0, props->Length()); + for (uint32_t i = 0; i < props->Length(); i++) { + printf("p[%d]\n", i); + } +} static bool NamedSetAccessBlocker(Local<v8::Object> obj, Local<Value> name, @@ -9694,6 +10643,7 @@ class RegExpInterruptTest { CHECK(regexp_success_); CHECK(gc_success_); } + private: // Number of garbage collections required. static const int kRequiredGCs = 5; @@ -9701,7 +10651,7 @@ class RegExpInterruptTest { class GCThread : public i::Thread { public: explicit GCThread(RegExpInterruptTest* test) - : test_(test) {} + : Thread("GCThread"), test_(test) {} virtual void Run() { test_->CollectGarbage(); } @@ -9715,7 +10665,7 @@ class RegExpInterruptTest { { v8::Locker lock; // TODO(lrn): Perhaps create some garbage before collecting. - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); gc_count_++; } i::OS::Sleep(1); @@ -9816,6 +10766,7 @@ class ApplyInterruptTest { CHECK(apply_success_); CHECK(gc_success_); } + private: // Number of garbage collections required. static const int kRequiredGCs = 2; @@ -9823,7 +10774,7 @@ class ApplyInterruptTest { class GCThread : public i::Thread { public: explicit GCThread(ApplyInterruptTest* test) - : test_(test) {} + : Thread("GCThread"), test_(test) {} virtual void Run() { test_->CollectGarbage(); } @@ -9836,7 +10787,7 @@ class ApplyInterruptTest { while (gc_during_apply_ < kRequiredGCs) { { v8::Locker lock; - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); gc_count_++; } i::OS::Sleep(1); @@ -9965,17 +10916,17 @@ static void MorphAString(i::String* string, CHECK(i::StringShape(string).IsExternal()); if (string->IsAsciiRepresentation()) { // Check old map is not symbol or long. - CHECK(string->map() == i::Heap::external_ascii_string_map()); + CHECK(string->map() == HEAP->external_ascii_string_map()); // Morph external string to be TwoByte string. - string->set_map(i::Heap::external_string_map()); + string->set_map(HEAP->external_string_map()); i::ExternalTwoByteString* morphed = i::ExternalTwoByteString::cast(string); morphed->set_resource(uc16_resource); } else { // Check old map is not symbol or long. - CHECK(string->map() == i::Heap::external_string_map()); + CHECK(string->map() == HEAP->external_string_map()); // Morph external string to be ASCII string. - string->set_map(i::Heap::external_ascii_string_map()); + string->set_map(HEAP->external_ascii_string_map()); i::ExternalAsciiString* morphed = i::ExternalAsciiString::cast(string); morphed->set_resource(ascii_resource); @@ -9999,9 +10950,9 @@ THREADED_TEST(MorphCompositeStringTest) { i::StrLength(c_string))); Local<String> lhs(v8::Utils::ToLocal( - i::Factory::NewExternalStringFromAscii(&ascii_resource))); + FACTORY->NewExternalStringFromAscii(&ascii_resource))); Local<String> rhs(v8::Utils::ToLocal( - i::Factory::NewExternalStringFromAscii(&ascii_resource))); + FACTORY->NewExternalStringFromAscii(&ascii_resource))); env->Global()->Set(v8_str("lhs"), lhs); env->Global()->Set(v8_str("rhs"), rhs); @@ -10086,12 +11037,12 @@ class RegExpStringModificationTest { // Create the input string for the regexp - the one we are going to change // properties of. - input_ = i::Factory::NewExternalStringFromAscii(&ascii_resource_); + input_ = FACTORY->NewExternalStringFromAscii(&ascii_resource_); // Inject the input as a global variable. i::Handle<i::String> input_name = - i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5)); - i::Top::global_context()->global()->SetProperty( + FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5)); + i::Isolate::Current()->global_context()->global()->SetProperty( *input_name, *input_, NONE, @@ -10109,8 +11060,8 @@ class RegExpStringModificationTest { CHECK(regexp_success_); CHECK(morph_success_); } - private: + private: // Number of string modifications required. static const int kRequiredModifications = 5; static const int kMaxModifications = 100; @@ -10118,7 +11069,7 @@ class RegExpStringModificationTest { class MorphThread : public i::Thread { public: explicit MorphThread(RegExpStringModificationTest* test) - : test_(test) {} + : Thread("MorphThread"), test_(test) {} virtual void Run() { test_->MorphString(); } @@ -10549,13 +11500,16 @@ THREADED_TEST(PixelArray) { LocalContext context; const int kElementCount = 260; uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); - i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount, - pixel_data); - i::Heap::CollectAllGarbage(false); // Force GC to trigger verification. + 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. for (int i = 0; i < kElementCount; i++) { pixels->set(i, i % 256); } - i::Heap::CollectAllGarbage(false); // Force GC to trigger verification. + HEAP->CollectAllGarbage(false); // Force GC to trigger verification. for (int i = 0; i < kElementCount; i++) { CHECK_EQ(i % 256, pixels->get(i)); CHECK_EQ(i % 256, pixel_data[i]); @@ -10617,14 +11571,14 @@ THREADED_TEST(PixelArray) { CHECK_EQ(28, result->Int32Value()); i::Handle<i::Smi> value(i::Smi::FromInt(2)); - i::SetElement(jsobj, 1, value); + i::SetElement(jsobj, 1, value, i::kNonStrictMode); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(256); - i::SetElement(jsobj, 1, value); + i::SetElement(jsobj, 1, value, i::kNonStrictMode); CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(-1); - i::SetElement(jsobj, 1, value); + i::SetElement(jsobj, 1, value, i::kNonStrictMode); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); result = CompileRun("for (var i = 0; i < 8; i++) {" @@ -10890,7 +11844,7 @@ THREADED_TEST(PixelArray) { " return sum; " "}" "for (var i = 0; i < 256; ++i) { pixels[i] = i; }" - "for (var i = 0; i < 10000; ++i) {" + "for (var i = 0; i < 5000; ++i) {" " result = pa_load(pixels);" "}" "result"); @@ -10907,7 +11861,7 @@ THREADED_TEST(PixelArray) { " }" " return sum; " "}" - "for (var i = 0; i < 100000; ++i) {" + "for (var i = 0; i < 5000; ++i) {" " pa_init(pixels);" "}" "result = pa_load(pixels);" @@ -10955,8 +11909,11 @@ THREADED_TEST(PixelArrayWithInterceptor) { LocalContext context; const int kElementCount = 260; uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); - i::Handle<i::PixelArray> pixels = - i::Factory::NewPixelArray(kElementCount, pixel_data); + i::Handle<i::ExternalPixelArray> pixels = + i::Handle<i::ExternalPixelArray>::cast( + FACTORY->NewExternalArray(kElementCount, + v8::kExternalPixelArray, + pixel_data)); for (int i = 0; i < kElementCount; i++) { pixels->set(i, i % 256); } @@ -10984,6 +11941,7 @@ static int ExternalArrayElementSize(v8::ExternalArrayType array_type) { switch (array_type) { case v8::kExternalByteArray: case v8::kExternalUnsignedByteArray: + case v8::kExternalPixelArray: return 1; break; case v8::kExternalShortArray: @@ -10995,6 +11953,9 @@ static int ExternalArrayElementSize(v8::ExternalArrayType array_type) { case v8::kExternalFloatArray: return 4; break; + case v8::kExternalDoubleArray: + return 8; + break; default: UNREACHABLE(); return -1; @@ -11016,12 +11977,12 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, static_cast<ElementType*>(malloc(kElementCount * element_size)); i::Handle<ExternalArrayClass> array = i::Handle<ExternalArrayClass>::cast( - i::Factory::NewExternalArray(kElementCount, array_type, array_data)); - i::Heap::CollectAllGarbage(false); // Force GC to trigger verification. + FACTORY->NewExternalArray(kElementCount, array_type, array_data)); + HEAP->CollectAllGarbage(false); // Force GC to trigger verification. for (int i = 0; i < kElementCount; i++) { array->set(i, static_cast<ElementType>(i)); } - i::Heap::CollectAllGarbage(false); // Force GC to trigger verification. + HEAP->CollectAllGarbage(false); // Force GC to trigger verification. for (int i = 0; i < kElementCount; i++) { CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get(i))); CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i])); @@ -11138,7 +12099,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " }" "}" "sum;"); - i::Heap::CollectAllGarbage(false); // Force GC to trigger verification. + HEAP->CollectAllGarbage(false); // Force GC to trigger verification. CHECK_EQ(28, result->Int32Value()); // Make sure out-of-range loads do not throw. @@ -11184,7 +12145,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, CHECK_EQ( 2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number())); - if (array_type != v8::kExternalFloatArray) { + if (array_type != v8::kExternalFloatArray && + array_type != v8::kExternalDoubleArray) { // Though the specification doesn't state it, be explicit about // converting NaNs and +/-Infinity to zero. result = CompileRun("for (var i = 0; i < 8; i++) {" @@ -11205,8 +12167,10 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " ext_array[i] = Infinity;" "}" "ext_array[5];"); - CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, + int expected_value = + (array_type == v8::kExternalPixelArray) ? 255 : 0; + CHECK_EQ(expected_value, result->Int32Value()); + CHECK_EQ(expected_value, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); result = CompileRun("for (var i = 0; i < 8; i++) {" @@ -11227,10 +12191,14 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, const char* signed_data = "var source_data = [0.6, 10.6, -0.6, -10.6];" "var expected_results = [0, 10, 0, -10];"; + const char* pixel_data = + "var source_data = [0.6, 10.6];" + "var expected_results = [1, 11];"; bool is_unsigned = (array_type == v8::kExternalUnsignedByteArray || array_type == v8::kExternalUnsignedShortArray || array_type == v8::kExternalUnsignedIntArray); + bool is_pixel_data = array_type == v8::kExternalPixelArray; i::OS::SNPrintF(test_buf, "%s" @@ -11243,11 +12211,46 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " (ext_array[5] == expected_results[i]);" "}" "all_passed;", - (is_unsigned ? unsigned_data : signed_data)); + (is_unsigned ? + unsigned_data : + (is_pixel_data ? pixel_data : signed_data))); result = CompileRun(test_buf.start()); CHECK_EQ(true, result->BooleanValue()); } + for (int i = 0; i < kElementCount; i++) { + array->set(i, static_cast<ElementType>(i)); + } + // Test complex assignments + result = CompileRun("function ee_op_test_complex_func(sum) {" + " for (var i = 0; i < 40; ++i) {" + " sum += (ext_array[i] += 1);" + " sum += (ext_array[i] -= 1);" + " } " + " return sum;" + "}" + "sum=0;" + "for (var i=0;i<10000;++i) {" + " sum=ee_op_test_complex_func(sum);" + "}" + "sum;"); + CHECK_EQ(16000000, result->Int32Value()); + + // Test count operations + result = CompileRun("function ee_op_test_count_func(sum) {" + " for (var i = 0; i < 40; ++i) {" + " sum += (++ext_array[i]);" + " sum += (--ext_array[i]);" + " } " + " return sum;" + "}" + "sum=0;" + "for (var i=0;i<10000;++i) {" + " sum=ee_op_test_count_func(sum);" + "}" + "sum;"); + CHECK_EQ(16000000, result->Int32Value()); + result = CompileRun("ext_array[3] = 33;" "delete ext_array[3];" "ext_array[3];"); @@ -11287,7 +12290,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, static_cast<ElementType*>(malloc(kLargeElementCount * element_size)); i::Handle<ExternalArrayClass> large_array = i::Handle<ExternalArrayClass>::cast( - i::Factory::NewExternalArray(kLargeElementCount, + FACTORY->NewExternalArray(kLargeElementCount, array_type, array_data)); v8::Handle<v8::Object> large_obj = v8::Object::New(); @@ -11354,6 +12357,95 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, free(large_array_data); } + // The "" property descriptor is overloaded to store information about + // the external array. Ensure that setting and accessing the "" property + // works (it should overwrite the information cached about the external + // array in the DescriptorArray) in various situations. + result = CompileRun("ext_array[''] = 23; ext_array['']"); + CHECK_EQ(23, result->Int32Value()); + + // Property "" set after the external array is associated with the object. + { + v8::Handle<v8::Object> obj2 = v8::Object::New(); + obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256)); + obj2->Set(v8_str(""), v8::Int32::New(1503)); + // Set the elements to be the external array. + obj2->SetIndexedPropertiesToExternalArrayData(array_data, + array_type, + kElementCount); + context->Global()->Set(v8_str("ext_array"), obj2); + result = CompileRun("ext_array['']"); + CHECK_EQ(1503, result->Int32Value()); + } + + // Property "" set after the external array is associated with the object. + { + v8::Handle<v8::Object> obj2 = v8::Object::New(); + obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256)); + // Set the elements to be the external array. + obj2->SetIndexedPropertiesToExternalArrayData(array_data, + array_type, + kElementCount); + obj2->Set(v8_str(""), v8::Int32::New(1503)); + context->Global()->Set(v8_str("ext_array"), obj2); + result = CompileRun("ext_array['']"); + CHECK_EQ(1503, result->Int32Value()); + } + + // Should reuse the map from previous test. + { + v8::Handle<v8::Object> obj2 = v8::Object::New(); + obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256)); + // Set the elements to be the external array. Should re-use the map + // from previous test. + obj2->SetIndexedPropertiesToExternalArrayData(array_data, + array_type, + kElementCount); + context->Global()->Set(v8_str("ext_array"), obj2); + result = CompileRun("ext_array['']"); + } + + // Property "" is a constant function that shouldn't not be interfered with + // when an external array is set. + { + v8::Handle<v8::Object> obj2 = v8::Object::New(); + // Start + obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256)); + + // Add a constant function to an object. + context->Global()->Set(v8_str("ext_array"), obj2); + result = CompileRun("ext_array[''] = function() {return 1503;};" + "ext_array['']();"); + + // Add an external array transition to the same map that + // has the constant transition. + v8::Handle<v8::Object> obj3 = v8::Object::New(); + obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256)); + obj3->SetIndexedPropertiesToExternalArrayData(array_data, + array_type, + kElementCount); + context->Global()->Set(v8_str("ext_array"), obj3); + } + + // If a external array transition is in the map, it should get clobbered + // by a constant function. + { + // Add an external array transition. + v8::Handle<v8::Object> obj3 = v8::Object::New(); + obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256)); + obj3->SetIndexedPropertiesToExternalArrayData(array_data, + array_type, + kElementCount); + + // Add a constant function to the same map that just got an external array + // transition. + v8::Handle<v8::Object> obj2 = v8::Object::New(); + obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256)); + context->Global()->Set(v8_str("ext_array"), obj2); + result = CompileRun("ext_array[''] = function() {return 1503;};" + "ext_array['']();"); + } + free(array_data); } @@ -11374,6 +12466,14 @@ THREADED_TEST(ExternalUnsignedByteArray) { } +THREADED_TEST(ExternalPixelArray) { + ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>( + v8::kExternalPixelArray, + 0, + 255); +} + + THREADED_TEST(ExternalShortArray) { ExternalArrayTestHelper<i::ExternalShortArray, int16_t>( v8::kExternalShortArray, @@ -11414,6 +12514,14 @@ THREADED_TEST(ExternalFloatArray) { } +THREADED_TEST(ExternalDoubleArray) { + ExternalArrayTestHelper<i::ExternalDoubleArray, double>( + v8::kExternalDoubleArray, + -500, + 500); +} + + THREADED_TEST(ExternalArrays) { TestExternalByteArray(); TestExternalUnsignedByteArray(); @@ -11451,6 +12559,8 @@ THREADED_TEST(ExternalArrayInfo) { ExternalArrayInfoTestHelper(v8::kExternalIntArray); ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray); ExternalArrayInfoTestHelper(v8::kExternalFloatArray); + ExternalArrayInfoTestHelper(v8::kExternalDoubleArray); + ExternalArrayInfoTestHelper(v8::kExternalPixelArray); } @@ -11714,7 +12824,8 @@ THREADED_TEST(IdleNotification) { static uint32_t* stack_limit; static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) { - stack_limit = reinterpret_cast<uint32_t*>(i::StackGuard::real_climit()); + stack_limit = reinterpret_cast<uint32_t*>( + i::Isolate::Current()->stack_guard()->real_climit()); return v8::Undefined(); } @@ -11799,28 +12910,14 @@ THREADED_TEST(GetHeapStatistics) { static double DoubleFromBits(uint64_t value) { double target; -#ifdef BIG_ENDIAN_FLOATING_POINT - const int kIntSize = 4; - // Somebody swapped the lower and higher half of doubles. - memcpy(&target, reinterpret_cast<char*>(&value) + kIntSize, kIntSize); - memcpy(reinterpret_cast<char*>(&target) + kIntSize, &value, kIntSize); -#else memcpy(&target, &value, sizeof(target)); -#endif return target; } static uint64_t DoubleToBits(double value) { uint64_t target; -#ifdef BIG_ENDIAN_FLOATING_POINT - const int kIntSize = 4; - // Somebody swapped the lower and higher half of doubles. - memcpy(&target, reinterpret_cast<char*>(&value) + kIntSize, kIntSize); - memcpy(reinterpret_cast<char*>(&target) + kIntSize, &value, kIntSize); -#else memcpy(&target, &value, sizeof(target)); -#endif return target; } @@ -11980,7 +13077,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_simple); other_context->Exit(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -12002,7 +13099,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_eval); other_context->Exit(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -12029,7 +13126,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_exception); other_context->Exit(); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -12247,26 +13344,26 @@ TEST(GCCallbacks) { v8::V8::AddGCEpilogueCallback(EpilogueCallback); CHECK_EQ(0, prologue_call_count); CHECK_EQ(0, epilogue_call_count); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(1, prologue_call_count); CHECK_EQ(1, epilogue_call_count); v8::V8::AddGCPrologueCallback(PrologueCallbackSecond); v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); 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); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); 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); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(2, prologue_call_count_second); @@ -12294,7 +13391,7 @@ THREADED_TEST(AddToJSFunctionResultCache) { " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;" " return 'PASSED';" "})()"; - i::Heap::ClearJSFunctionResultCaches(); + HEAP->ClearJSFunctionResultCaches(); ExpectString(code, "PASSED"); } @@ -12318,7 +13415,7 @@ THREADED_TEST(FillJSFunctionResultCache) { " return 'FAILED: k0CacheSize is too small';" " return 'PASSED';" "})()"; - i::Heap::ClearJSFunctionResultCaches(); + HEAP->ClearJSFunctionResultCaches(); ExpectString(code, "PASSED"); } @@ -12343,7 +13440,7 @@ THREADED_TEST(RoundRobinGetFromCache) { " };" " return 'PASSED';" "})()"; - i::Heap::ClearJSFunctionResultCaches(); + HEAP->ClearJSFunctionResultCaches(); ExpectString(code, "PASSED"); } @@ -12368,7 +13465,7 @@ THREADED_TEST(ReverseGetFromCache) { " };" " return 'PASSED';" "})()"; - i::Heap::ClearJSFunctionResultCaches(); + HEAP->ClearJSFunctionResultCaches(); ExpectString(code, "PASSED"); } @@ -12386,7 +13483,7 @@ THREADED_TEST(TestEviction) { " };" " return 'PASSED';" "})()"; - i::Heap::ClearJSFunctionResultCaches(); + HEAP->ClearJSFunctionResultCaches(); ExpectString(code, "PASSED"); } @@ -12476,7 +13573,7 @@ THREADED_TEST(TwoByteStringInAsciiCons) { void FailedAccessCheckCallbackGC(Local<v8::Object> target, v8::AccessType type, Local<v8::Value> data) { - i::Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); } @@ -12557,6 +13654,396 @@ TEST(GCInFailedAccessCheckCallback) { v8::V8::SetFailedAccessCheckCallbackFunction(NULL); } +TEST(DefaultIsolateGetCurrent) { + CHECK(v8::Isolate::GetCurrent() != NULL); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate()); + printf("*** %s\n", "DefaultIsolateGetCurrent success"); +} + +TEST(IsolateNewDispose) { + v8::Isolate* current_isolate = v8::Isolate::GetCurrent(); + v8::Isolate* isolate = v8::Isolate::New(); + CHECK(isolate != NULL); + CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate()); + CHECK(current_isolate != isolate); + CHECK(current_isolate == v8::Isolate::GetCurrent()); + + v8::V8::SetFatalErrorHandler(StoringErrorCallback); + last_location = last_message = NULL; + isolate->Dispose(); + CHECK_EQ(last_location, NULL); + CHECK_EQ(last_message, NULL); +} + +TEST(IsolateEnterExitDefault) { + v8::HandleScope scope; + LocalContext context; + v8::Isolate* current_isolate = v8::Isolate::GetCurrent(); + CHECK(current_isolate != NULL); // Default isolate. + ExpectString("'hello'", "hello"); + current_isolate->Enter(); + ExpectString("'still working'", "still working"); + current_isolate->Exit(); + ExpectString("'still working 2'", "still working 2"); + current_isolate->Exit(); + // Default isolate is always, well, 'default current'. + CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate); + // Still working since default isolate is auto-entering any thread + // that has no isolate and attempts to execute V8 APIs. + ExpectString("'still working 3'", "still working 3"); +} + +TEST(DisposeDefaultIsolate) { + v8::V8::SetFatalErrorHandler(StoringErrorCallback); + + // Run some V8 code to trigger default isolate to become 'current'. + v8::HandleScope scope; + LocalContext context; + ExpectString("'run some V8'", "run some V8"); + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate()); + last_location = last_message = NULL; + isolate->Dispose(); + // It is not possible to dispose default isolate via Isolate API. + CHECK_NE(last_location, NULL); + CHECK_NE(last_message, NULL); +} + +TEST(RunDefaultAndAnotherIsolate) { + v8::HandleScope scope; + LocalContext context; + + // Enter new isolate. + v8::Isolate* isolate = v8::Isolate::New(); + CHECK(isolate); + isolate->Enter(); + { // Need this block because subsequent Exit() will deallocate Heap, + // so we need all scope objects to be deconstructed when it happens. + v8::HandleScope scope_new; + LocalContext context_new; + + // Run something in new isolate. + CompileRun("var foo = 153;"); + ExpectTrue("function f() { return foo == 153; }; f()"); + } + isolate->Exit(); + + // This runs automatically in default isolate. + // Variables in another isolate should be not available. + ExpectTrue("function f() {" + " try {" + " foo;" + " return false;" + " } catch(e) {" + " return true;" + " }" + "};" + "var bar = 371;" + "f()"); + + v8::V8::SetFatalErrorHandler(StoringErrorCallback); + last_location = last_message = NULL; + isolate->Dispose(); + CHECK_EQ(last_location, NULL); + CHECK_EQ(last_message, NULL); + + // Check that default isolate still runs. + ExpectTrue("function f() { return bar == 371; }; f()"); +} + +TEST(DisposeIsolateWhenInUse) { + v8::Isolate* isolate = v8::Isolate::New(); + CHECK(isolate); + isolate->Enter(); + v8::HandleScope scope; + LocalContext context; + // Run something in this isolate. + ExpectTrue("true"); + v8::V8::SetFatalErrorHandler(StoringErrorCallback); + last_location = last_message = NULL; + // Still entered, should fail. + isolate->Dispose(); + CHECK_NE(last_location, NULL); + CHECK_NE(last_message, NULL); +} + +TEST(RunTwoIsolatesOnSingleThread) { + // Run isolate 1. + v8::Isolate* isolate1 = v8::Isolate::New(); + isolate1->Enter(); + v8::Persistent<v8::Context> context1 = v8::Context::New(); + + { + v8::Context::Scope cscope(context1); + v8::HandleScope scope; + // Run something in new isolate. + CompileRun("var foo = 'isolate 1';"); + ExpectString("function f() { return foo; }; f()", "isolate 1"); + } + + // Run isolate 2. + v8::Isolate* isolate2 = v8::Isolate::New(); + v8::Persistent<v8::Context> context2; + + { + v8::Isolate::Scope iscope(isolate2); + context2 = v8::Context::New(); + v8::Context::Scope cscope(context2); + v8::HandleScope scope; + + // Run something in new isolate. + CompileRun("var foo = 'isolate 2';"); + ExpectString("function f() { return foo; }; f()", "isolate 2"); + } + + { + v8::Context::Scope cscope(context1); + v8::HandleScope scope; + // Now again in isolate 1 + ExpectString("function f() { return foo; }; f()", "isolate 1"); + } + + isolate1->Exit(); + + // Run some stuff in default isolate. + v8::Persistent<v8::Context> context_default = v8::Context::New(); + + { + v8::Context::Scope cscope(context_default); + v8::HandleScope scope; + // Variables in other isolates should be not available, verify there + // is an exception. + ExpectTrue("function f() {" + " try {" + " foo;" + " return false;" + " } catch(e) {" + " return true;" + " }" + "};" + "var isDefaultIsolate = true;" + "f()"); + } + + isolate1->Enter(); + + { + v8::Isolate::Scope iscope(isolate2); + v8::Context::Scope cscope(context2); + v8::HandleScope scope; + ExpectString("function f() { return foo; }; f()", "isolate 2"); + } + + { + v8::Context::Scope cscope(context1); + v8::HandleScope scope; + ExpectString("function f() { return foo; }; f()", "isolate 1"); + } + + { + v8::Isolate::Scope iscope(isolate2); + context2.Dispose(); + } + + context1.Dispose(); + isolate1->Exit(); + + v8::V8::SetFatalErrorHandler(StoringErrorCallback); + last_location = last_message = NULL; + + isolate1->Dispose(); + CHECK_EQ(last_location, NULL); + CHECK_EQ(last_message, NULL); + + isolate2->Dispose(); + CHECK_EQ(last_location, NULL); + CHECK_EQ(last_message, NULL); + + // Check that default isolate still runs. + { + v8::Context::Scope cscope(context_default); + v8::HandleScope scope; + ExpectTrue("function f() { return isDefaultIsolate; }; f()"); + } +} + +static int CalcFibonacci(v8::Isolate* isolate, int limit) { + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope; + LocalContext context; + i::ScopedVector<char> code(1024); + i::OS::SNPrintF(code, "function fib(n) {" + " if (n <= 2) return 1;" + " return fib(n-1) + fib(n-2);" + "}" + "fib(%d)", limit); + Local<Value> value = CompileRun(code.start()); + CHECK(value->IsNumber()); + return static_cast<int>(value->NumberValue()); +} + +class IsolateThread : public v8::internal::Thread { + public: + IsolateThread(v8::Isolate* isolate, int fib_limit) + : Thread("IsolateThread"), + isolate_(isolate), + fib_limit_(fib_limit), + result_(0) { } + + void Run() { + result_ = CalcFibonacci(isolate_, fib_limit_); + } + + int result() { return result_; } + + private: + v8::Isolate* isolate_; + int fib_limit_; + int result_; +}; + +TEST(MultipleIsolatesOnIndividualThreads) { + v8::Isolate* isolate1 = v8::Isolate::New(); + v8::Isolate* isolate2 = v8::Isolate::New(); + + IsolateThread thread1(isolate1, 21); + IsolateThread thread2(isolate2, 12); + + // Compute some fibonacci numbers on 3 threads in 3 isolates. + thread1.Start(); + thread2.Start(); + + int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21); + int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12); + + thread1.Join(); + thread2.Join(); + + // Compare results. The actual fibonacci numbers for 12 and 21 are taken + // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number + CHECK_EQ(result1, 10946); + CHECK_EQ(result2, 144); + CHECK_EQ(result1, thread1.result()); + CHECK_EQ(result2, thread2.result()); + + isolate1->Dispose(); + isolate2->Dispose(); +} + +TEST(IsolateDifferentContexts) { + v8::Isolate* isolate = v8::Isolate::New(); + Persistent<v8::Context> context; + { + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + context = v8::Context::New(); + v8::Context::Scope context_scope(context); + Local<Value> v = CompileRun("2"); + CHECK(v->IsNumber()); + CHECK_EQ(2, static_cast<int>(v->NumberValue())); + } + { + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + context = v8::Context::New(); + v8::Context::Scope context_scope(context); + Local<Value> v = CompileRun("22"); + CHECK(v->IsNumber()); + CHECK_EQ(22, static_cast<int>(v->NumberValue())); + } +} + +class InitDefaultIsolateThread : public v8::internal::Thread { + public: + enum TestCase { + IgnoreOOM, + SetResourceConstraints, + SetFatalHandler, + SetCounterFunction, + SetCreateHistogramFunction, + SetAddHistogramSampleFunction + }; + + explicit InitDefaultIsolateThread(TestCase testCase) + : Thread("InitDefaultIsolateThread"), + testCase_(testCase), + result_(false) { } + + void Run() { + switch (testCase_) { + case IgnoreOOM: + v8::V8::IgnoreOutOfMemoryException(); + break; + + case SetResourceConstraints: { + static const int K = 1024; + v8::ResourceConstraints constraints; + constraints.set_max_young_space_size(256 * K); + constraints.set_max_old_space_size(4 * K * K); + v8::SetResourceConstraints(&constraints); + break; + } + + case SetFatalHandler: + v8::V8::SetFatalErrorHandler(NULL); + break; + + case SetCounterFunction: + v8::V8::SetCounterFunction(NULL); + break; + + case SetCreateHistogramFunction: + v8::V8::SetCreateHistogramFunction(NULL); + break; + + case SetAddHistogramSampleFunction: + v8::V8::SetAddHistogramSampleFunction(NULL); + break; + } + result_ = true; + } + + bool result() { return result_; } + + private: + TestCase testCase_; + bool result_; +}; + + +static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) { + InitDefaultIsolateThread thread(testCase); + thread.Start(); + thread.Join(); + CHECK_EQ(thread.result(), true); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread1) { + InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread2) { + InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread3) { + InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread4) { + InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread5) { + InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction); +} + +TEST(InitializeDefaultIsolateOnSecondaryThread6) { + InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction); +} + TEST(StringCheckMultipleContexts) { const char* code = @@ -12660,7 +14147,7 @@ TEST(DontDeleteCellLoadIC) { "})()", "ReferenceError: cell is not defined"); CompileRun("cell = \"new_second\";"); - i::Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); ExpectString("readCell()", "new_second"); ExpectString("readCell()", "new_second"); } @@ -12723,48 +14210,6 @@ TEST(DontDeleteCellLoadICAPI) { } -TEST(GlobalLoadICGC) { - const char* function_code = - "function readCell() { while (true) { return cell; } }"; - - // Check inline load code for a don't delete cell is cleared during - // GC. - { - v8::HandleScope scope; - LocalContext context; - CompileRun("var cell = \"value\";"); - ExpectBoolean("delete cell", false); - CompileRun(function_code); - ExpectString("readCell()", "value"); - ExpectString("readCell()", "value"); - } - { - v8::HandleScope scope; - LocalContext context2; - // Hold the code object in the second context. - CompileRun(function_code); - CheckSurvivingGlobalObjectsCount(1); - } - - // Check inline load code for a deletable cell is cleared during GC. - { - v8::HandleScope scope; - LocalContext context; - CompileRun("cell = \"value\";"); - CompileRun(function_code); - ExpectString("readCell()", "value"); - ExpectString("readCell()", "value"); - } - { - v8::HandleScope scope; - LocalContext context2; - // Hold the code object in the second context. - CompileRun(function_code); - CheckSurvivingGlobalObjectsCount(1); - } -} - - TEST(RegExp) { v8::HandleScope scope; LocalContext context; @@ -12821,6 +14266,11 @@ TEST(RegExp) { context->Global()->Set(v8_str("re"), re); ExpectTrue("re.test('FoobarbaZ')"); + // 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::TryCatch try_catch; re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); CHECK(re.IsEmpty()); @@ -12891,3 +14341,321 @@ TEST(DefinePropertyPostDetach) { context->DetachGlobal(); define_property->Call(proxy, 0, NULL); } + + +static void InstallContextId(v8::Handle<Context> context, int id) { + Context::Scope scope(context); + CompileRun("Object.prototype").As<Object>()-> + Set(v8_str("context_id"), v8::Integer::New(id)); +} + + +static void CheckContextId(v8::Handle<Object> object, int expected) { + CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value()); +} + + +THREADED_TEST(CreationContext) { + HandleScope handle_scope; + Persistent<Context> context1 = Context::New(); + InstallContextId(context1, 1); + Persistent<Context> context2 = Context::New(); + InstallContextId(context2, 2); + Persistent<Context> context3 = Context::New(); + InstallContextId(context3, 3); + + Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(); + + Local<Object> object1; + Local<Function> func1; + { + Context::Scope scope(context1); + object1 = Object::New(); + func1 = tmpl->GetFunction(); + } + + Local<Object> object2; + Local<Function> func2; + { + Context::Scope scope(context2); + object2 = Object::New(); + func2 = tmpl->GetFunction(); + } + + Local<Object> instance1; + Local<Object> instance2; + + { + Context::Scope scope(context3); + instance1 = func1->NewInstance(); + instance2 = func2->NewInstance(); + } + + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + + { + Context::Scope scope(context1); + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + } + + { + Context::Scope scope(context2); + CHECK(object1->CreationContext() == context1); + CheckContextId(object1, 1); + CHECK(func1->CreationContext() == context1); + CheckContextId(func1, 1); + CHECK(instance1->CreationContext() == context1); + CheckContextId(instance1, 1); + CHECK(object2->CreationContext() == context2); + CheckContextId(object2, 2); + CHECK(func2->CreationContext() == context2); + CheckContextId(func2, 2); + CHECK(instance2->CreationContext() == context2); + CheckContextId(instance2, 2); + } + + context1.Dispose(); + context2.Dispose(); + context3.Dispose(); +} + + +Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index, + const AccessorInfo& info) { + if (index == 42) return v8_str("yes"); + return Handle<v8::Integer>(); +} + + +Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property, + const AccessorInfo& info) { + if (property->Equals(v8_str("foo"))) return v8_str("yes"); + return Handle<Value>(); +} + + +Handle<v8::Integer> HasOwnPropertyIndexedPropertyQuery( + uint32_t index, const AccessorInfo& info) { + if (index == 42) return v8_num(1).As<v8::Integer>(); + return Handle<v8::Integer>(); +} + + +Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery( + Local<String> property, const AccessorInfo& info) { + if (property->Equals(v8_str("foo"))) return v8_num(1).As<v8::Integer>(); + return Handle<v8::Integer>(); +} + + +Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery2( + Local<String> property, const AccessorInfo& info) { + if (property->Equals(v8_str("bar"))) return v8_num(1).As<v8::Integer>(); + return Handle<v8::Integer>(); +} + + +Handle<Value> HasOwnPropertyAccessorGetter(Local<String> property, + const AccessorInfo& info) { + return v8_str("yes"); +} + + +TEST(HasOwnProperty) { + v8::HandleScope scope; + LocalContext env; + { // Check normal properties and defined getters. + Handle<Value> value = CompileRun( + "function Foo() {" + " this.foo = 11;" + " this.__defineGetter__('baz', function() { return 1; });" + "};" + "function Bar() { " + " this.bar = 13;" + " this.__defineGetter__('bla', function() { return 2; });" + "};" + "Bar.prototype = new Foo();" + "new Bar();"); + CHECK(value->IsObject()); + Handle<Object> object = value->ToObject(); + CHECK(object->Has(v8_str("foo"))); + CHECK(!object->HasOwnProperty(v8_str("foo"))); + CHECK(object->HasOwnProperty(v8_str("bar"))); + CHECK(object->Has(v8_str("baz"))); + CHECK(!object->HasOwnProperty(v8_str("baz"))); + CHECK(object->HasOwnProperty(v8_str("bla"))); + } + { // Check named getter interceptors. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter); + Handle<Object> instance = templ->NewInstance(); + CHECK(!instance->HasOwnProperty(v8_str("42"))); + CHECK(instance->HasOwnProperty(v8_str("foo"))); + CHECK(!instance->HasOwnProperty(v8_str("bar"))); + } + { // Check indexed getter interceptors. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter); + Handle<Object> instance = templ->NewInstance(); + CHECK(instance->HasOwnProperty(v8_str("42"))); + CHECK(!instance->HasOwnProperty(v8_str("43"))); + CHECK(!instance->HasOwnProperty(v8_str("foo"))); + } + { // Check named query interceptors. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery); + Handle<Object> instance = templ->NewInstance(); + CHECK(instance->HasOwnProperty(v8_str("foo"))); + CHECK(!instance->HasOwnProperty(v8_str("bar"))); + } + { // Check indexed query interceptors. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery); + Handle<Object> instance = templ->NewInstance(); + CHECK(instance->HasOwnProperty(v8_str("42"))); + CHECK(!instance->HasOwnProperty(v8_str("41"))); + } + { // Check callbacks. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter); + Handle<Object> instance = templ->NewInstance(); + CHECK(instance->HasOwnProperty(v8_str("foo"))); + CHECK(!instance->HasOwnProperty(v8_str("bar"))); + } + { // Check that query wins on disagreement. + Handle<ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter, + 0, + HasOwnPropertyNamedPropertyQuery2); + Handle<Object> instance = templ->NewInstance(); + CHECK(!instance->HasOwnProperty(v8_str("foo"))); + CHECK(instance->HasOwnProperty(v8_str("bar"))); + } +} + + +void CheckCodeGenerationAllowed() { + Handle<Value> result = CompileRun("eval('42')"); + CHECK_EQ(42, result->Int32Value()); + result = CompileRun("(function(e) { return e('42'); })(eval)"); + CHECK_EQ(42, result->Int32Value()); + result = CompileRun("var f = new Function('return 42'); f()"); + CHECK_EQ(42, result->Int32Value()); +} + + +void CheckCodeGenerationDisallowed() { + TryCatch try_catch; + + Handle<Value> result = CompileRun("eval('42')"); + CHECK(result.IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + + result = CompileRun("(function(e) { return e('42'); })(eval)"); + CHECK(result.IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + + result = CompileRun("var f = new Function('return 42'); f()"); + CHECK(result.IsEmpty()); + CHECK(try_catch.HasCaught()); +} + + +bool CodeGenerationAllowed(Local<Context> context) { + ApiTestFuzzer::Fuzz(); + return true; +} + + +bool CodeGenerationDisallowed(Local<Context> context) { + ApiTestFuzzer::Fuzz(); + return false; +} + + +THREADED_TEST(AllowCodeGenFromStrings) { + v8::HandleScope scope; + LocalContext context; + + // eval and the Function constructor allowed by default. + CheckCodeGenerationAllowed(); + + // Disallow eval and the Function constructor. + context->AllowCodeGenerationFromStrings(false); + CheckCodeGenerationDisallowed(); + + // Allow again. + context->AllowCodeGenerationFromStrings(true); + CheckCodeGenerationAllowed(); + + // Disallow but setting a global callback that will allow the calls. + context->AllowCodeGenerationFromStrings(false); + V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed); + CheckCodeGenerationAllowed(); + + // Set a callback that disallows the code generation. + V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed); + CheckCodeGenerationDisallowed(); +} + + +static v8::Handle<Value> NonObjectThis(const v8::Arguments& args) { + return v8::Undefined(); +} + + +THREADED_TEST(CallAPIFunctionOnNonObject) { + v8::HandleScope scope; + LocalContext context; + Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis); + Handle<Function> function = templ->GetFunction(); + context->Global()->Set(v8_str("f"), function); + TryCatch try_catch; + CompileRun("f.call(2)"); +} + + +// Regression test for issue 1470. +THREADED_TEST(ReadOnlyIndexedProperties) { + v8::HandleScope scope; + Local<ObjectTemplate> templ = ObjectTemplate::New(); + + LocalContext context; + Local<v8::Object> obj = templ->NewInstance(); + context->Global()->Set(v8_str("obj"), obj); + obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly); + obj->Set(v8_str("1"), v8_str("foobar")); + CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1"))); + obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly); + obj->Set(v8_num(2), v8_str("foobar")); + CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2))); + + // Test non-smi case. + obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly); + obj->Set(v8_str("2000000000"), v8_str("foobar")); + CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000"))); +} diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 43cf580a5..17032035c 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2010 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: @@ -39,7 +39,8 @@ using namespace v8::internal; // Define these function prototypes to match JSEntryFunction in execution.cc. typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); -typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); +typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); +typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); static v8::Persistent<v8::Context> env; @@ -58,17 +59,17 @@ TEST(0) { InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); __ add(r0, r0, Operand(r1)); __ mov(pc, Operand(lr)); CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -84,7 +85,7 @@ TEST(1) { InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); Label L, C; __ mov(r1, Operand(r0)); @@ -102,10 +103,10 @@ TEST(1) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -121,7 +122,7 @@ TEST(2) { InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); Label L, C; __ mov(r1, Operand(r0)); @@ -139,7 +140,7 @@ TEST(2) { // some relocated stuff here, not executed __ RecordComment("dead code, just testing relocations"); - __ mov(r0, Operand(Factory::true_value())); + __ mov(r0, Operand(FACTORY->true_value())); __ RecordComment("dead code, just testing immediate operands"); __ mov(r0, Operand(-1)); __ mov(r0, Operand(0xFF000000)); @@ -148,10 +149,10 @@ TEST(2) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -174,7 +175,7 @@ TEST(3) { } T; T t; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); Label L, C; __ mov(ip, Operand(sp)); @@ -196,10 +197,10 @@ TEST(3) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -232,6 +233,8 @@ TEST(4) { double g; double h; int i; + double m; + double n; float x; float y; } T; @@ -239,7 +242,7 @@ TEST(4) { // Create a function that accepts &t, and loads, manipulates, and stores // the doubles and floats. - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); Label L, C; @@ -297,14 +300,22 @@ TEST(4) { __ vabs(d0, d2); __ vstr(d0, r4, OFFSET_OF(T, h)); + // Test vneg. + __ vldr(d1, r4, OFFSET_OF(T, m)); + __ vneg(d0, d1); + __ vstr(d0, r4, OFFSET_OF(T, m)); + __ vldr(d1, r4, OFFSET_OF(T, n)); + __ vneg(d0, d1); + __ vstr(d0, r4, OFFSET_OF(T, n)); + __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -319,12 +330,16 @@ TEST(4) { t.g = -2718.2818; t.h = 31415926.5; t.i = 0; + t.m = -2718.2818; + t.n = 123.456; t.x = 4.5; t.y = 9.0; Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); USE(dummy); CHECK_EQ(4.5, t.y); CHECK_EQ(9.0, t.x); + CHECK_EQ(-123.456, t.n); + CHECK_EQ(2718.2818, t.m); CHECK_EQ(2, t.i); CHECK_EQ(2718.2818, t.g); CHECK_EQ(31415926.5, t.h); @@ -343,7 +358,7 @@ TEST(5) { InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); if (CpuFeatures::IsSupported(ARMv7)) { CpuFeatures::Scope scope(ARMv7); @@ -357,10 +372,10 @@ TEST(5) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -379,7 +394,7 @@ TEST(6) { InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); if (CpuFeatures::IsSupported(ARMv7)) { CpuFeatures::Scope scope(ARMv7); @@ -392,10 +407,10 @@ TEST(6) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -422,7 +437,7 @@ static void TestRoundingMode(VCVTTypes types, InitializeVM(); v8::HandleScope scope; - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); if (CpuFeatures::IsSupported(VFP3)) { CpuFeatures::Scope scope(VFP3); @@ -468,10 +483,10 @@ static void TestRoundingMode(VCVTTypes types, CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -594,4 +609,405 @@ TEST(7) { TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); } +TEST(8) { + // Test VFP multi load/store with ia_w. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + } D; + D d; + + typedef struct { + float a; + float b; + float c; + float d; + float e; + float f; + float g; + float h; + } F; + F f; + + // Create a function that uses vldm/vstm to move some double and + // single precision values around in memory. + Assembler assm(Isolate::Current(), NULL, 0); + + if (CpuFeatures::IsSupported(VFP3)) { + CpuFeatures::Scope scope(VFP3); + + __ mov(ip, Operand(sp)); + __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); + __ sub(fp, ip, Operand(4)); + + __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ vldm(ia_w, r4, d0, d3); + __ vldm(ia_w, r4, d4, d7); + + __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ vstm(ia_w, r4, d6, d7); + __ vstm(ia_w, r4, d0, d5); + + __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ vldm(ia_w, r4, s0, s3); + __ vldm(ia_w, r4, s4, s7); + + __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ vstm(ia_w, r4, s6, s7); + __ vstm(ia_w, r4, s0, s5); + + __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef DEBUG + Code::cast(code)->Print(); +#endif + F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); + d.a = 1.1; + d.b = 2.2; + d.c = 3.3; + d.d = 4.4; + d.e = 5.5; + d.f = 6.6; + d.g = 7.7; + d.h = 8.8; + + f.a = 1.0; + f.b = 2.0; + f.c = 3.0; + f.d = 4.0; + f.e = 5.0; + f.f = 6.0; + f.g = 7.0; + f.h = 8.0; + + Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); + USE(dummy); + + CHECK_EQ(7.7, d.a); + CHECK_EQ(8.8, d.b); + CHECK_EQ(1.1, d.c); + CHECK_EQ(2.2, d.d); + CHECK_EQ(3.3, d.e); + CHECK_EQ(4.4, d.f); + CHECK_EQ(5.5, d.g); + CHECK_EQ(6.6, d.h); + + CHECK_EQ(7.0, f.a); + CHECK_EQ(8.0, f.b); + CHECK_EQ(1.0, f.c); + CHECK_EQ(2.0, f.d); + CHECK_EQ(3.0, f.e); + CHECK_EQ(4.0, f.f); + CHECK_EQ(5.0, f.g); + CHECK_EQ(6.0, f.h); + } +} + + +TEST(9) { + // Test VFP multi load/store with ia. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + } D; + D d; + + typedef struct { + float a; + float b; + float c; + float d; + float e; + float f; + float g; + float h; + } F; + F f; + + // Create a function that uses vldm/vstm to move some double and + // single precision values around in memory. + Assembler assm(Isolate::Current(), NULL, 0); + + if (CpuFeatures::IsSupported(VFP3)) { + CpuFeatures::Scope scope(VFP3); + + __ mov(ip, Operand(sp)); + __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); + __ sub(fp, ip, Operand(4)); + + __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ vldm(ia, r4, d0, d3); + __ add(r4, r4, Operand(4 * 8)); + __ vldm(ia, r4, d4, d7); + + __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ vstm(ia, r4, d6, d7); + __ add(r4, r4, Operand(2 * 8)); + __ vstm(ia, r4, d0, d5); + + __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ vldm(ia, r4, s0, s3); + __ add(r4, r4, Operand(4 * 4)); + __ vldm(ia, r4, s4, s7); + + __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ vstm(ia, r4, s6, s7); + __ add(r4, r4, Operand(2 * 4)); + __ vstm(ia, r4, s0, s5); + + __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef DEBUG + Code::cast(code)->Print(); +#endif + F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); + d.a = 1.1; + d.b = 2.2; + d.c = 3.3; + d.d = 4.4; + d.e = 5.5; + d.f = 6.6; + d.g = 7.7; + d.h = 8.8; + + f.a = 1.0; + f.b = 2.0; + f.c = 3.0; + f.d = 4.0; + f.e = 5.0; + f.f = 6.0; + f.g = 7.0; + f.h = 8.0; + + Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); + USE(dummy); + + CHECK_EQ(7.7, d.a); + CHECK_EQ(8.8, d.b); + CHECK_EQ(1.1, d.c); + CHECK_EQ(2.2, d.d); + CHECK_EQ(3.3, d.e); + CHECK_EQ(4.4, d.f); + CHECK_EQ(5.5, d.g); + CHECK_EQ(6.6, d.h); + + CHECK_EQ(7.0, f.a); + CHECK_EQ(8.0, f.b); + CHECK_EQ(1.0, f.c); + CHECK_EQ(2.0, f.d); + CHECK_EQ(3.0, f.e); + CHECK_EQ(4.0, f.f); + CHECK_EQ(5.0, f.g); + CHECK_EQ(6.0, f.h); + } +} + + +TEST(10) { + // Test VFP multi load/store with db_w. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + } D; + D d; + + typedef struct { + float a; + float b; + float c; + float d; + float e; + float f; + float g; + float h; + } F; + F f; + + // Create a function that uses vldm/vstm to move some double and + // single precision values around in memory. + Assembler assm(Isolate::Current(), NULL, 0); + + if (CpuFeatures::IsSupported(VFP3)) { + CpuFeatures::Scope scope(VFP3); + + __ mov(ip, Operand(sp)); + __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); + __ sub(fp, ip, Operand(4)); + + __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ vldm(db_w, r4, d4, d7); + __ vldm(db_w, r4, d0, d3); + + __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ vstm(db_w, r4, d0, d5); + __ vstm(db_w, r4, d6, d7); + + __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ vldm(db_w, r4, s4, s7); + __ vldm(db_w, r4, s0, s3); + + __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ vstm(db_w, r4, s0, s5); + __ vstm(db_w, r4, s6, s7); + + __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef DEBUG + Code::cast(code)->Print(); +#endif + F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); + d.a = 1.1; + d.b = 2.2; + d.c = 3.3; + d.d = 4.4; + d.e = 5.5; + d.f = 6.6; + d.g = 7.7; + d.h = 8.8; + + f.a = 1.0; + f.b = 2.0; + f.c = 3.0; + f.d = 4.0; + f.e = 5.0; + f.f = 6.0; + f.g = 7.0; + f.h = 8.0; + + Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); + USE(dummy); + + CHECK_EQ(7.7, d.a); + CHECK_EQ(8.8, d.b); + CHECK_EQ(1.1, d.c); + CHECK_EQ(2.2, d.d); + CHECK_EQ(3.3, d.e); + CHECK_EQ(4.4, d.f); + CHECK_EQ(5.5, d.g); + CHECK_EQ(6.6, d.h); + + CHECK_EQ(7.0, f.a); + CHECK_EQ(8.0, f.b); + CHECK_EQ(1.0, f.c); + CHECK_EQ(2.0, f.d); + CHECK_EQ(3.0, f.e); + CHECK_EQ(4.0, f.f); + CHECK_EQ(5.0, f.g); + CHECK_EQ(6.0, f.h); + } +} + + +TEST(11) { + // Test instructions using the carry flag. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + int32_t a; + int32_t b; + int32_t c; + int32_t d; + } I; + I i; + + i.a = 0xabcd0001; + i.b = 0xabcd0000; + + Assembler assm(Isolate::Current(), NULL, 0); + + // Test HeapObject untagging. + __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a))); + __ mov(r1, Operand(r1, ASR, 1), SetCC); + __ adc(r1, r1, Operand(r1), LeaveCC, cs); + __ str(r1, MemOperand(r0, OFFSET_OF(I, a))); + + __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b))); + __ mov(r2, Operand(r2, ASR, 1), SetCC); + __ adc(r2, r2, Operand(r2), LeaveCC, cs); + __ str(r2, MemOperand(r0, OFFSET_OF(I, b))); + + // Test corner cases. + __ mov(r1, Operand(0xffffffff)); + __ mov(r2, Operand(0)); + __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. + __ adc(r3, r1, Operand(r2)); + __ str(r3, MemOperand(r0, OFFSET_OF(I, c))); + + __ mov(r1, Operand(0xffffffff)); + __ mov(r2, Operand(0)); + __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. + __ adc(r3, r1, Operand(r2)); + __ str(r3, MemOperand(r0, OFFSET_OF(I, d))); + + __ mov(pc, Operand(lr)); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef DEBUG + Code::cast(code)->Print(); +#endif + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(0xabcd0001, i.a); + CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); + CHECK_EQ(0x00000000, i.c); + CHECK_EQ(0xffffffff, i.d); +} + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-ia32.cc b/deps/v8/test/cctest/test-assembler-ia32.cc index 14692ff1e..e9d799b54 100644 --- a/deps/v8/test/cctest/test-assembler-ia32.cc +++ b/deps/v8/test/cctest/test-assembler-ia32.cc @@ -61,7 +61,7 @@ TEST(AssemblerIa320) { v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ mov(eax, Operand(esp, 4)); __ add(eax, Operand(esp, 8)); @@ -69,10 +69,10 @@ TEST(AssemblerIa320) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))-> - ToObjectChecked(); + 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(); @@ -89,7 +89,7 @@ TEST(AssemblerIa321) { v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); Label L, C; __ mov(edx, Operand(esp, 4)); @@ -102,15 +102,15 @@ TEST(AssemblerIa321) { __ bind(&C); __ test(edx, Operand(edx)); - __ j(not_zero, &L, taken); + __ j(not_zero, &L); __ ret(0); CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))-> - ToObjectChecked(); + 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(); @@ -127,7 +127,7 @@ TEST(AssemblerIa322) { v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); Label L, C; __ mov(edx, Operand(esp, 4)); @@ -140,20 +140,19 @@ TEST(AssemblerIa322) { __ bind(&C); __ test(edx, Operand(edx)); - __ j(not_zero, &L, taken); + __ j(not_zero, &L); __ ret(0); // some relocated stuff here, not executed - __ mov(eax, Factory::true_value()); + __ mov(eax, FACTORY->true_value()); __ jmp(NULL, RelocInfo::RUNTIME_ENTRY); CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); - + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef OBJECT_PRINT Code::cast(code)->Print(); @@ -168,13 +167,13 @@ TEST(AssemblerIa322) { typedef int (*F3)(float x); TEST(AssemblerIa323) { + InitializeVM(); if (!CpuFeatures::IsSupported(SSE2)) return; - InitializeVM(); v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); CHECK(CpuFeatures::IsSupported(SSE2)); { CpuFeatures::Scope fscope(SSE2); @@ -184,10 +183,10 @@ TEST(AssemblerIa323) { CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); // don't print the code - our disassembler can't handle cvttss2si // instead print bytes Disassembler::Dump(stdout, @@ -203,13 +202,13 @@ TEST(AssemblerIa323) { typedef int (*F4)(double x); TEST(AssemblerIa324) { + InitializeVM(); if (!CpuFeatures::IsSupported(SSE2)) return; - InitializeVM(); v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); CHECK(CpuFeatures::IsSupported(SSE2)); CpuFeatures::Scope fscope(SSE2); @@ -218,10 +217,10 @@ TEST(AssemblerIa324) { CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); // don't print the code - our disassembler can't handle cvttsd2si // instead print bytes Disassembler::Dump(stdout, @@ -240,17 +239,17 @@ TEST(AssemblerIa325) { v8::HandleScope scope; v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE)); __ ret(0); CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); F0 f = FUNCTION_CAST<F0>(code->entry()); int res = f(); CHECK_EQ(42, res); @@ -260,14 +259,14 @@ TEST(AssemblerIa325) { typedef double (*F5)(double x, double y); TEST(AssemblerIa326) { + InitializeVM(); if (!CpuFeatures::IsSupported(SSE2)) return; - InitializeVM(); v8::HandleScope scope; CHECK(CpuFeatures::IsSupported(SSE2)); CpuFeatures::Scope fscope(SSE2); v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ movdbl(xmm0, Operand(esp, 1 * kPointerSize)); __ movdbl(xmm1, Operand(esp, 3 * kPointerSize)); @@ -284,10 +283,10 @@ TEST(AssemblerIa326) { CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); #ifdef DEBUG ::printf("\n---\n"); // don't print the code - our disassembler can't handle SSE instructions @@ -306,14 +305,14 @@ TEST(AssemblerIa326) { typedef double (*F6)(int x); TEST(AssemblerIa328) { + InitializeVM(); if (!CpuFeatures::IsSupported(SSE2)) return; - InitializeVM(); v8::HandleScope scope; CHECK(CpuFeatures::IsSupported(SSE2)); CpuFeatures::Scope fscope(SSE2); v8::internal::byte buffer[256]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ mov(eax, Operand(esp, 4)); __ cvtsi2sd(xmm0, Operand(eax)); // Copy xmm0 to st(0) using eight bytes of stack. @@ -324,10 +323,10 @@ TEST(AssemblerIa328) { __ ret(0); CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); CHECK(code->IsCode()); #ifdef OBJECT_PRINT Code::cast(code)->Print(); @@ -346,16 +345,16 @@ TEST(AssemblerIa329) { InitializeVM(); v8::HandleScope scope; v8::internal::byte buffer[256]; - MacroAssembler assm(buffer, sizeof buffer); + MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer); enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 }; Label equal_l, less_l, greater_l, nan_l; __ fld_d(Operand(esp, 3 * kPointerSize)); __ fld_d(Operand(esp, 1 * kPointerSize)); __ FCmp(); - __ j(parity_even, &nan_l, taken); - __ j(equal, &equal_l, taken); - __ j(below, &less_l, taken); - __ j(above, &greater_l, taken); + __ j(parity_even, &nan_l); + __ j(equal, &equal_l); + __ j(below, &less_l); + __ j(above, &greater_l); __ mov(eax, kUndefined); __ ret(0); @@ -379,10 +378,10 @@ TEST(AssemblerIa329) { CodeDesc desc; assm.GetCode(&desc); - Code* code = Code::cast(Heap::CreateCode( + Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); CHECK(code->IsCode()); #ifdef OBJECT_PRINT Code::cast(code)->Print(); diff --git a/deps/v8/test/cctest/test-assembler-mips.cc b/deps/v8/test/cctest/test-assembler-mips.cc index ecb42e2f7..8ac89f6b3 100644 --- a/deps/v8/test/cctest/test-assembler-mips.cc +++ b/deps/v8/test/cctest/test-assembler-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2010 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: @@ -59,11 +59,12 @@ static void InitializeVM() { #define __ assm. + TEST(MIPS0) { InitializeVM(); v8::HandleScope scope; - MacroAssembler assm(NULL, 0); + MacroAssembler assm(Isolate::Current(), NULL, 0); // Addition. __ addu(v0, a0, a1); @@ -72,14 +73,11 @@ TEST(MIPS0) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - NULL, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); -#ifdef DEBUG - Code::cast(code)->Print(); -#endif F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); ::printf("f() = %d\n", res); @@ -91,7 +89,7 @@ TEST(MIPS1) { InitializeVM(); v8::HandleScope scope; - MacroAssembler assm(NULL, 0); + MacroAssembler assm(Isolate::Current(), NULL, 0); Label L, C; __ mov(a1, a0); @@ -100,12 +98,12 @@ TEST(MIPS1) { __ nop(); __ bind(&L); - __ add(v0, v0, a1); + __ addu(v0, v0, a1); __ addiu(a1, a1, -1); __ bind(&C); __ xori(v1, a1, 0); - __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE)); + __ Branch(&L, ne, v1, Operand(0)); __ nop(); __ jr(ra); @@ -113,14 +111,11 @@ TEST(MIPS1) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - NULL, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); -#ifdef DEBUG - Code::cast(code)->Print(); -#endif F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); ::printf("f() = %d\n", res); @@ -132,7 +127,7 @@ TEST(MIPS2) { InitializeVM(); v8::HandleScope scope; - MacroAssembler assm(NULL, 0); + MacroAssembler assm(Isolate::Current(), NULL, 0); Label exit, error; @@ -166,62 +161,81 @@ TEST(MIPS2) { __ srav(v0, v0, t0); // 0xff234560 __ sllv(v0, v0, t0); // 0xf2345600 __ srlv(v0, v0, t0); // 0x0f234560 - __ Branch(ne, &error, v0, Operand(0x0f234560)); + __ Branch(&error, ne, v0, Operand(0x0f234560)); __ nop(); - __ add(v0, t0, t1); // 0x00001238 - __ sub(v0, v0, t0); // 0x00001234 - __ Branch(ne, &error, v0, Operand(0x00001234)); + __ addu(v0, t0, t1); // 0x00001238 + __ subu(v0, v0, t0); // 0x00001234 + __ Branch(&error, ne, v0, Operand(0x00001234)); __ nop(); __ addu(v1, t3, t0); - __ Branch(ne, &error, v1, Operand(0x80000003)); + __ Branch(&error, ne, v1, Operand(0x80000003)); __ nop(); __ subu(v1, t7, t0); // 0x7ffffffc - __ Branch(ne, &error, v1, Operand(0x7ffffffc)); + __ Branch(&error, ne, v1, Operand(0x7ffffffc)); __ nop(); __ and_(v0, t1, t2); // 0x00001230 __ or_(v0, v0, t1); // 0x00001234 __ xor_(v0, v0, t2); // 0x1234444c __ nor(v0, v0, t2); // 0xedcba987 - __ Branch(ne, &error, v0, Operand(0xedcba983)); + __ Branch(&error, ne, v0, Operand(0xedcba983)); __ nop(); __ slt(v0, t7, t3); - __ Branch(ne, &error, v0, Operand(0x1)); + __ Branch(&error, ne, v0, Operand(0x1)); __ nop(); __ sltu(v0, t7, t3); - __ Branch(ne, &error, v0, Operand(0x0)); + __ Branch(&error, ne, v0, Operand(0x0)); __ nop(); // End of SPECIAL class. - __ addi(v0, zero_reg, 0x7421); // 0x00007421 - __ addi(v0, v0, -0x1); // 0x00007420 + __ addiu(v0, zero_reg, 0x7421); // 0x00007421 + __ addiu(v0, v0, -0x1); // 0x00007420 __ addiu(v0, v0, -0x20); // 0x00007400 - __ Branch(ne, &error, v0, Operand(0x00007400)); + __ Branch(&error, ne, v0, Operand(0x00007400)); __ nop(); __ addiu(v1, t3, 0x1); // 0x80000000 - __ Branch(ne, &error, v1, Operand(0x80000000)); + __ Branch(&error, ne, v1, Operand(0x80000000)); __ nop(); __ slti(v0, t1, 0x00002000); // 0x1 __ slti(v0, v0, 0xffff8000); // 0x0 - __ Branch(ne, &error, v0, Operand(0x0)); + __ Branch(&error, ne, v0, Operand(0x0)); __ nop(); __ sltiu(v0, t1, 0x00002000); // 0x1 __ sltiu(v0, v0, 0x00008000); // 0x1 - __ Branch(ne, &error, v0, Operand(0x1)); + __ Branch(&error, ne, v0, Operand(0x1)); __ nop(); __ andi(v0, t1, 0xf0f0); // 0x00001030 __ ori(v0, v0, 0x8a00); // 0x00009a30 __ xori(v0, v0, 0x83cc); // 0x000019fc - __ Branch(ne, &error, v0, Operand(0x000019fc)); + __ Branch(&error, ne, v0, Operand(0x000019fc)); __ nop(); __ lui(v1, 0x8123); // 0x81230000 - __ Branch(ne, &error, v1, Operand(0x81230000)); + __ Branch(&error, ne, v1, Operand(0x81230000)); __ nop(); + // Bit twiddling instructions & conditional moves. + // Uses t0-t7 as set above. + __ clz(v0, t0); // 29 + __ clz(v1, t1); // 19 + __ addu(v0, v0, v1); // 48 + __ clz(v1, t2); // 3 + __ addu(v0, v0, v1); // 51 + __ 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). + __ Ins(a0, t1, 12, 8); // 0x7ff34fff + __ Branch(&error, ne, a0, Operand(0x7ff34fff)); + __ 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. + __ Branch(&error, ne, a0, Operand(t6)); + // Everything was correctly executed. Load the expected result. __ li(v0, 0x31415926); __ b(&exit); @@ -229,6 +243,7 @@ TEST(MIPS2) { __ bind(&error); // Got an error. Return a wrong result. + __ li(v0, 666); __ bind(&exit); __ jr(ra); @@ -236,18 +251,1012 @@ TEST(MIPS2) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - NULL, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); -#ifdef DEBUG - Code::cast(code)->Print(); -#endif F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); ::printf("f() = %d\n", res); CHECK_EQ(0x31415926, res); } + +TEST(MIPS3) { + // Test floating point instructions. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + double d; + double e; + double f; + double g; + } T; + T t; + + // Create a function that accepts &t, and loads, manipulates, and stores + // the doubles t.a ... t.f. + MacroAssembler assm(Isolate::Current(), NULL, 0); + Label L, C; + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); + __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ add_d(f8, f4, f6); + __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. + + __ mov_d(f10, f8); // c + __ neg_d(f12, f6); // -b + __ sub_d(f10, f10, f12); + __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). + + __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. + + __ li(t0, 120); + __ mtc1(t0, f14); + __ cvt_d_w(f14, f14); // f14 = 120.0. + __ mul_d(f10, f10, f14); + __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. + + __ div_d(f12, f10, f4); + __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. + + __ sqrt_d(f14, f12); + __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); + // g = sqrt(f) = 10.97451593465515908537 + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.a = 1.5e14; + t.b = 2.75e11; + t.c = 0.0; + t.d = 0.0; + t.e = 0.0; + t.f = 0.0; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + CHECK_EQ(1.5e14, t.a); + CHECK_EQ(1.5e14, t.b); + CHECK_EQ(1.50275e14, t.c); + CHECK_EQ(1.50550e14, t.d); + CHECK_EQ(1.8066e16, t.e); + CHECK_EQ(120.44, t.f); + CHECK_EQ(10.97451593465515908537, t.g); + } +} + + +TEST(MIPS4) { + // Test moves between floating point and integer registers. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + } T; + T t; + + Assembler assm(Isolate::Current(), NULL, 0); + Label L, C; + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); + __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + + // Swap f4 and f6, by using four integer registers, t0-t3. + __ mfc1(t0, f4); + __ mfc1(t1, f5); + __ mfc1(t2, f6); + __ mfc1(t3, f7); + + __ mtc1(t0, f6); + __ mtc1(t1, f7); + __ mtc1(t2, f4); + __ mtc1(t3, f5); + + // Store the swapped f4 and f5 back to memory. + __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); + __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.a = 1.5e22; + t.b = 2.75e11; + t.c = 17.17; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(2.75e11, t.a); + CHECK_EQ(2.75e11, t.b); + CHECK_EQ(1.5e22, t.c); + } +} + + +TEST(MIPS5) { + // Test conversions between doubles and integers. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + int i; + int j; + } T; + T t; + + Assembler assm(Isolate::Current(), NULL, 0); + Label L, C; + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + // Load all structure elements to registers. + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); + __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); + __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); + + // Convert double in f4 to int in element i. + __ cvt_w_d(f8, f4); + __ mfc1(t2, f8); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); + + // Convert double in f6 to int in element j. + __ cvt_w_d(f10, f6); + __ mfc1(t3, f10); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); + + // Convert int in original i (t0) to double in a. + __ mtc1(t0, f12); + __ cvt_d_w(f0, f12); + __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); + + // Convert int in original j (t1) to double in b. + __ mtc1(t1, f14); + __ cvt_d_w(f2, f14); + __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.a = 1.5e4; + t.b = 2.75e8; + t.i = 12345678; + t.j = -100000; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(12345678.0, t.a); + CHECK_EQ(-100000.0, t.b); + CHECK_EQ(15000, t.i); + CHECK_EQ(275000000, t.j); + } +} + + +TEST(MIPS6) { + // Test simple memory loads and stores. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + uint32_t ui; + int32_t si; + int32_t r1; + int32_t r2; + int32_t r3; + int32_t r4; + int32_t r5; + int32_t r6; + } T; + T t; + + Assembler assm(Isolate::Current(), NULL, 0); + Label L, C; + + // Basic word load/store. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) ); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) ); + + // lh with positive data. + __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) ); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) ); + + // lh with negative data. + __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) ); + + // lhu with negative data. + __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) ); + + // lb with negative data. + __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) ); + __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) ); + + // sh writes only 1/2 of word. + __ lui(t5, 0x3333); + __ ori(t5, t5, 0x3333); + __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); + __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) ); + __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.ui = 0x11223344; + t.si = 0x99aabbcc; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(0x11223344, t.r1); + CHECK_EQ(0x3344, t.r2); + CHECK_EQ(0xffffbbcc, t.r3); + CHECK_EQ(0x0000bbcc, t.r4); + CHECK_EQ(0xffffffcc, t.r5); + CHECK_EQ(0x3333bbcc, t.r6); +} + + +TEST(MIPS7) { + // Test floating point compare and branch instructions. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + double c; + double d; + double e; + double f; + int32_t result; + } T; + T t; + + // Create a function that accepts &t, and loads, manipulates, and stores + // the doubles t.a ... t.f. + MacroAssembler assm(Isolate::Current(), NULL, 0); + Label neither_is_nan, less_than, outa_here; + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); + __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ c(UN, D, f4, f6); + __ bc1f(&neither_is_nan); + __ nop(); + __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ Branch(&outa_here); + + __ bind(&neither_is_nan); + + __ c(OLT, D, f6, f4, 2); + __ bc1t(&less_than, 2); + __ nop(); + __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ Branch(&outa_here); + + __ bind(&less_than); + __ Addu(t0, zero_reg, Operand(1)); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. + + + // This test-case should have additional tests. + + __ bind(&outa_here); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.a = 1.5e14; + t.b = 2.75e11; + t.c = 2.0; + t.d = -4.0; + t.e = 0.0; + t.f = 0.0; + t.result = 0; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + CHECK_EQ(1.5e14, t.a); + CHECK_EQ(2.75e11, t.b); + CHECK_EQ(1, t.result); + } +} + + +TEST(MIPS8) { + // Test ROTR and ROTRV instructions. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + int32_t input; + int32_t result_rotr_4; + int32_t result_rotr_8; + int32_t result_rotr_12; + int32_t result_rotr_16; + int32_t result_rotr_20; + int32_t result_rotr_24; + int32_t result_rotr_28; + int32_t result_rotrv_4; + int32_t result_rotrv_8; + int32_t result_rotrv_12; + int32_t result_rotrv_16; + int32_t result_rotrv_20; + int32_t result_rotrv_24; + int32_t result_rotrv_28; + } T; + T t; + + MacroAssembler assm(Isolate::Current(), NULL, 0); + + // Basic word load. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) ); + + // ROTR instruction (called through the Ror macro). + __ Ror(t1, t0, 0x0004); + __ Ror(t2, t0, 0x0008); + __ Ror(t3, t0, 0x000c); + __ Ror(t4, t0, 0x0010); + __ Ror(t5, t0, 0x0014); + __ Ror(t6, t0, 0x0018); + __ Ror(t7, t0, 0x001c); + + // Basic word store. + __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) ); + __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) ); + __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) ); + __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) ); + __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) ); + + // ROTRV instruction (called through the Ror macro). + __ li(t7, 0x0004); + __ Ror(t1, t0, t7); + __ li(t7, 0x0008); + __ Ror(t2, t0, t7); + __ li(t7, 0x000C); + __ Ror(t3, t0, t7); + __ li(t7, 0x0010); + __ Ror(t4, t0, t7); + __ li(t7, 0x0014); + __ Ror(t5, t0, t7); + __ li(t7, 0x0018); + __ Ror(t6, t0, t7); + __ li(t7, 0x001C); + __ Ror(t7, t0, t7); + + // Basic word store. + __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) ); + __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) ); + __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) ); + __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) ); + __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.input = 0x12345678; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0); + USE(dummy); + CHECK_EQ(0x81234567, t.result_rotr_4); + CHECK_EQ(0x78123456, t.result_rotr_8); + CHECK_EQ(0x67812345, t.result_rotr_12); + CHECK_EQ(0x56781234, t.result_rotr_16); + CHECK_EQ(0x45678123, t.result_rotr_20); + CHECK_EQ(0x34567812, t.result_rotr_24); + CHECK_EQ(0x23456781, t.result_rotr_28); + + CHECK_EQ(0x81234567, t.result_rotrv_4); + CHECK_EQ(0x78123456, t.result_rotrv_8); + CHECK_EQ(0x67812345, t.result_rotrv_12); + CHECK_EQ(0x56781234, t.result_rotrv_16); + CHECK_EQ(0x45678123, t.result_rotrv_20); + CHECK_EQ(0x34567812, t.result_rotrv_24); + CHECK_EQ(0x23456781, t.result_rotrv_28); +} + + +TEST(MIPS9) { + // Test BRANCH improvements. + InitializeVM(); + v8::HandleScope scope; + + MacroAssembler assm(Isolate::Current(), NULL, 0); + Label exit, exit2, exit3; + + __ Branch(&exit, ge, a0, Operand(0x00000000)); + __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); + __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); + + __ bind(&exit); + __ bind(&exit2); + __ bind(&exit3); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +} + + +TEST(MIPS10) { + // Test conversions between doubles and long integers. + // Test hos the long ints map to FP regs pairs. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double a; + double b; + int32_t dbl_mant; + int32_t dbl_exp; + int32_t long_hi; + int32_t long_lo; + int32_t b_long_hi; + int32_t b_long_lo; + } T; + T t; + + Assembler assm(Isolate::Current(), NULL, 0); + Label L, C; + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + // Load all structure elements to registers. + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); + + // Save the raw bits of the double. + __ mfc1(t0, f0); + __ mfc1(t1, f1); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); + + // Convert double in f0 to long, save hi/lo parts. + __ cvt_l_d(f0, f0); + __ mfc1(t0, f0); // f0 has LS 32 bits of long. + __ mfc1(t1, f1); // f1 has MS 32 bits of long. + __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo))); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi))); + + // Convert the b long integers to double b. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo))); + __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi))); + __ mtc1(t0, f8); // f8 has LS 32-bits. + __ mtc1(t1, f9); // f9 has MS 32-bits. + __ cvt_d_l(f10, f8); + __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.a = 2.147483647e9; // 0x7fffffff -> 0x41DFFFFFFFC00000 as double. + t.b_long_hi = 0x000000ff; // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double. + t.b_long_lo = 0x00ff00ff; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(0x41DFFFFF, t.dbl_exp); + CHECK_EQ(0xFFC00000, t.dbl_mant); + CHECK_EQ(0, t.long_hi); + CHECK_EQ(0x7fffffff, t.long_lo); + // 0xFF00FF00FF -> 1.095233372415e12. + CHECK_EQ(1.095233372415e12, t.b); + } +} + + +TEST(MIPS11) { + // Test LWL, LWR, SWL and SWR instructions. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + int32_t reg_init; + int32_t mem_init; + int32_t lwl_0; + int32_t lwl_1; + int32_t lwl_2; + int32_t lwl_3; + int32_t lwr_0; + int32_t lwr_1; + int32_t lwr_2; + int32_t lwr_3; + int32_t swl_0; + int32_t swl_1; + int32_t swl_2; + int32_t swl_3; + int32_t swr_0; + int32_t swr_1; + int32_t swr_2; + int32_t swr_3; + } T; + T t; + + Assembler assm(Isolate::Current(), NULL, 0); + + // Test all combinations of LWL and vAddr. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) ); + + __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) ); + + __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) ); + + __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) ); + + // Test all combinations of LWR and vAddr. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) ); + + __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) ); + + __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) ); + + __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) ); + + // Test all combinations of SWL and vAddr. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); + __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); + + __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) ); + __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) ); + + __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) ); + __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) ); + + __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) ); + __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) ); + + // Test all combinations of SWR and vAddr. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); + __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); + + __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) ); + __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) ); + + __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) ); + __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) ); + + __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); + __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) ); + __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); + __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.reg_init = 0xaabbccdd; + t.mem_init = 0x11223344; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(0x44bbccdd, t.lwl_0); + CHECK_EQ(0x3344ccdd, t.lwl_1); + CHECK_EQ(0x223344dd, t.lwl_2); + CHECK_EQ(0x11223344, t.lwl_3); + + CHECK_EQ(0x11223344, t.lwr_0); + CHECK_EQ(0xaa112233, t.lwr_1); + CHECK_EQ(0xaabb1122, t.lwr_2); + CHECK_EQ(0xaabbcc11, t.lwr_3); + + CHECK_EQ(0x112233aa, t.swl_0); + CHECK_EQ(0x1122aabb, t.swl_1); + CHECK_EQ(0x11aabbcc, t.swl_2); + CHECK_EQ(0xaabbccdd, t.swl_3); + + CHECK_EQ(0xaabbccdd, t.swr_0); + CHECK_EQ(0xbbccdd44, t.swr_1); + CHECK_EQ(0xccdd3344, t.swr_2); + CHECK_EQ(0xdd223344, t.swr_3); +} + + +TEST(MIPS12) { + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + int32_t x; + int32_t y; + int32_t y1; + int32_t y2; + int32_t y3; + int32_t y4; + } T; + T t; + + MacroAssembler assm(Isolate::Current(), NULL, 0); + + __ mov(t6, fp); // Save frame pointer. + __ mov(fp, a0); // Access struct T by fp. + __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) ); + __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) ); + + __ addu(t1, t0, t3); + __ subu(t4, t0, t3); + __ nop(); + __ push(t0); // These instructions disappear after opt. + __ Pop(); + __ addu(t0, t0, t0); + __ nop(); + __ Pop(); // These instructions disappear after opt. + __ push(t3); + __ nop(); + __ push(t3); // These instructions disappear after opt. + __ pop(t3); + __ nop(); + __ push(t3); + __ pop(t4); + __ nop(); + __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); + __ nop(); + __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); + __ nop(); + __ push(t1); + __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); + __ pop(t1); + __ nop(); + __ push(t1); + __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ pop(t1); + __ nop(); + __ push(t1); + __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ pop(t2); + __ nop(); + __ push(t2); + __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ pop(t1); + __ nop(); + __ push(t1); + __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ pop(t3); + __ nop(); + + __ mov(fp, t6); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + t.x = 1; + t.y = 2; + t.y1 = 3; + t.y2 = 4; + t.y3 = 0XBABA; + t.y4 = 0xDEDA; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(3, t.y1); +} + + +TEST(MIPS13) { + // Test Cvt_d_uw and Trunc_uw_d macros. + InitializeVM(); + v8::HandleScope scope; + + typedef struct { + double cvt_big_out; + double cvt_small_out; + uint32_t trunc_big_out; + uint32_t trunc_small_out; + uint32_t cvt_big_in; + uint32_t cvt_small_in; + } T; + T t; + + MacroAssembler assm(Isolate::Current(), NULL, 0); + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); + __ Cvt_d_uw(f10, t0); + __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); + + __ Trunc_uw_d(f10, f10); + __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); + + __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); + __ Cvt_d_uw(f8, t0); + __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); + + __ Trunc_uw_d(f8, f8); + __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + + t.cvt_big_in = 0xFFFFFFFF; + t.cvt_small_in = 333; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in)); + CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in)); + + CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in)); + CHECK_EQ(static_cast<int>(t.trunc_small_out), + static_cast<int>(t.cvt_small_in)); + } +} + + +TEST(MIPS14) { + // Test round, floor, ceil, trunc, cvt. + InitializeVM(); + v8::HandleScope scope; + +#define ROUND_STRUCT_ELEMENT(x) \ + int32_t x##_up_out; \ + int32_t x##_down_out; \ + int32_t neg_##x##_up_out; \ + int32_t neg_##x##_down_out; \ + uint32_t x##_err1_out; \ + uint32_t x##_err2_out; \ + uint32_t x##_err3_out; \ + uint32_t x##_err4_out; \ + int32_t x##_invalid_result; + + typedef struct { + double round_up_in; + double round_down_in; + double neg_round_up_in; + double neg_round_down_in; + double err1_in; + double err2_in; + double err3_in; + double err4_in; + + ROUND_STRUCT_ELEMENT(round) + ROUND_STRUCT_ELEMENT(floor) + ROUND_STRUCT_ELEMENT(ceil) + ROUND_STRUCT_ELEMENT(trunc) + ROUND_STRUCT_ELEMENT(cvt) + } T; + T t; + +#undef ROUND_STRUCT_ELEMENT + + MacroAssembler assm(Isolate::Current(), NULL, 0); + + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + + // Save FCSR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); +#define RUN_ROUND_TEST(x) \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \ + __ x##_w_d(f0, f0); \ + __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \ + __ x##_w_d(f0, f0); \ + __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \ + __ x##_w_d(f0, f0); \ + __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \ + __ x##_w_d(f0, f0); \ + __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \ + __ ctc1(zero_reg, FCSR); \ + __ x##_w_d(f0, f0); \ + __ cfc1(a2, FCSR); \ + __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \ + __ ctc1(zero_reg, FCSR); \ + __ x##_w_d(f0, f0); \ + __ cfc1(a2, FCSR); \ + __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \ + __ ctc1(zero_reg, FCSR); \ + __ x##_w_d(f0, f0); \ + __ cfc1(a2, FCSR); \ + __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \ + \ + __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \ + __ ctc1(zero_reg, FCSR); \ + __ x##_w_d(f0, f0); \ + __ cfc1(a2, FCSR); \ + __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \ + __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result))); + + RUN_ROUND_TEST(round) + RUN_ROUND_TEST(floor) + RUN_ROUND_TEST(ceil) + RUN_ROUND_TEST(trunc) + RUN_ROUND_TEST(cvt) + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); + + t.round_up_in = 123.51; + t.round_down_in = 123.49; + t.neg_round_up_in = -123.5; + t.neg_round_down_in = -123.49; + t.err1_in = 123.51; + t.err2_in = 1; + t.err3_in = static_cast<double>(1) + 0xFFFFFFFF; + t.err4_in = NAN; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + +#define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) +#define CHECK_ROUND_RESULT(type) \ + CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ + CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ + CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ + CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ + CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result); + + CHECK_ROUND_RESULT(round); + CHECK_ROUND_RESULT(floor); + CHECK_ROUND_RESULT(ceil); + CHECK_ROUND_RESULT(cvt); + } +} + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc index 5d292df05..ea70f5420 100644 --- a/deps/v8/test/cctest/test-assembler-x64.cc +++ b/deps/v8/test/cctest/test-assembler-x64.cc @@ -35,31 +35,31 @@ #include "serialize.h" #include "cctest.h" -using v8::internal::byte; -using v8::internal::OS; using v8::internal::Assembler; -using v8::internal::Operand; +using v8::internal::CodeDesc; +using v8::internal::FUNCTION_CAST; using v8::internal::Immediate; +using v8::internal::Isolate; using v8::internal::Label; +using v8::internal::OS; +using v8::internal::Operand; +using v8::internal::byte; +using v8::internal::greater; +using v8::internal::less_equal; +using v8::internal::not_equal; +using v8::internal::r13; +using v8::internal::r15; +using v8::internal::r8; +using v8::internal::r9; using v8::internal::rax; -using v8::internal::rsi; -using v8::internal::rdi; +using v8::internal::rbp; using v8::internal::rcx; +using v8::internal::rdi; using v8::internal::rdx; -using v8::internal::rbp; +using v8::internal::rsi; using v8::internal::rsp; -using v8::internal::r8; -using v8::internal::r9; -using v8::internal::r12; -using v8::internal::r13; using v8::internal::times_1; -using v8::internal::FUNCTION_CAST; -using v8::internal::CodeDesc; -using v8::internal::less_equal; -using v8::internal::not_equal; -using v8::internal::greater; - // Test the x64 assembler by compiling some simple functions into // a buffer and executing them. These tests do not initialize the // V8 library, create a context, or use any V8 objects. @@ -86,13 +86,14 @@ static const v8::internal::Register arg2 = rsi; TEST(AssemblerX64ReturnOperation) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that copies argument 2 and returns it. __ movq(rax, arg2); @@ -107,13 +108,14 @@ TEST(AssemblerX64ReturnOperation) { } TEST(AssemblerX64StackOperations) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that copies argument 2 and returns it. // We compile without stack frame pointers, so the gdb debugger shows @@ -138,13 +140,14 @@ TEST(AssemblerX64StackOperations) { } TEST(AssemblerX64ArithmeticOperations) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that adds arguments returning the sum. __ movq(rax, arg2); @@ -159,13 +162,14 @@ TEST(AssemblerX64ArithmeticOperations) { } TEST(AssemblerX64ImulOperation) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that multiplies arguments returning the high // word. @@ -186,13 +190,14 @@ TEST(AssemblerX64ImulOperation) { } TEST(AssemblerX64MemoryOperands) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that copies argument 2 and returns it. __ push(rbp); @@ -219,13 +224,14 @@ TEST(AssemblerX64MemoryOperands) { } TEST(AssemblerX64ControlFlow) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble a simple function that copies argument 1 and returns it. __ push(rbp); @@ -247,13 +253,14 @@ TEST(AssemblerX64ControlFlow) { } TEST(AssemblerX64LoopImmediates) { + OS::Setup(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); CHECK(buffer); - Assembler assm(buffer, static_cast<int>(actual_size)); + Assembler assm(Isolate::Current(), buffer, static_cast<int>(actual_size)); // Assemble two loops using rax as counter, and verify the ending counts. Label Fail; __ movq(rax, Immediate(-3)); @@ -317,7 +324,7 @@ TEST(OperandRegisterDependency) { CHECK(Operand(rsp, offset).AddressUsesRegister(rsp)); CHECK(!Operand(rsp, offset).AddressUsesRegister(rax)); - CHECK(!Operand(rsp, offset).AddressUsesRegister(r12)); + CHECK(!Operand(rsp, offset).AddressUsesRegister(r15)); CHECK(Operand(rbp, offset).AddressUsesRegister(rbp)); CHECK(!Operand(rbp, offset).AddressUsesRegister(rax)); @@ -333,7 +340,7 @@ TEST(OperandRegisterDependency) { CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp)); CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp)); CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax)); - CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r12)); + CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15)); CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13)); } } diff --git a/deps/v8/test/cctest/test-ast.cc b/deps/v8/test/cctest/test-ast.cc index 9c292bcfc..d1e537d9d 100644 --- a/deps/v8/test/cctest/test-ast.cc +++ b/deps/v8/test/cctest/test-ast.cc @@ -35,10 +35,11 @@ using namespace v8::internal; TEST(List) { + v8::internal::V8::Initialize(NULL); List<AstNode*>* list = new List<AstNode*>(0); CHECK_EQ(0, list->length()); - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); AstNode* node = new EmptyStatement(); list->Add(node); CHECK_EQ(1, list->length()); diff --git a/deps/v8/test/cctest/test-circular-queue.cc b/deps/v8/test/cctest/test-circular-queue.cc index ce9a42e81..c4e5c4c24 100644 --- a/deps/v8/test/cctest/test-circular-queue.cc +++ b/deps/v8/test/cctest/test-circular-queue.cc @@ -88,7 +88,8 @@ class ProducerThread: public i::Thread { int records_per_chunk, Record value, i::Semaphore* finished) - : scq_(scq), + : Thread("producer"), + scq_(scq), records_per_chunk_(records_per_chunk), value_(value), finished_(finished) { } diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index 9f21b78dd..4c5f197bc 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -31,10 +31,11 @@ #include "v8.h" #include "compiler.h" +#include "disasm.h" +#include "disassembler.h" #include "execution.h" #include "factory.h" #include "platform.h" -#include "top.h" #include "cctest.h" using namespace v8::internal; @@ -99,21 +100,21 @@ static void InitializeVM() { static MaybeObject* GetGlobalProperty(const char* name) { - Handle<String> symbol = Factory::LookupAsciiSymbol(name); - return Top::context()->global()->GetProperty(*symbol); + Handle<String> symbol = FACTORY->LookupAsciiSymbol(name); + return Isolate::Current()->context()->global()->GetProperty(*symbol); } static void SetGlobalProperty(const char* name, Object* value) { Handle<Object> object(value); - Handle<String> symbol = Factory::LookupAsciiSymbol(name); - Handle<JSObject> global(Top::context()->global()); + Handle<String> symbol = FACTORY->LookupAsciiSymbol(name); + Handle<JSObject> global(Isolate::Current()->context()->global()); SetProperty(global, symbol, object, NONE, kNonStrictMode); } static Handle<JSFunction> Compile(const char* source) { - Handle<String> source_code(Factory::NewStringFromUtf8(CStrVector(source))); + Handle<String> source_code(FACTORY->NewStringFromUtf8(CStrVector(source))); Handle<SharedFunctionInfo> shared_function = Compiler::Compile(source_code, Handle<String>(), @@ -123,8 +124,8 @@ static Handle<JSFunction> Compile(const char* source) { NULL, Handle<String>::null(), NOT_NATIVES_CODE); - return Factory::NewFunctionFromSharedFunctionInfo(shared_function, - Top::global_context()); + return FACTORY->NewFunctionFromSharedFunctionInfo(shared_function, + Isolate::Current()->global_context()); } @@ -137,7 +138,7 @@ static double Inc(int x) { if (fun.is_null()) return -1; bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); @@ -158,7 +159,7 @@ static double Add(int x, int y) { SetGlobalProperty("x", Smi::FromInt(x)); SetGlobalProperty("y", Smi::FromInt(y)); bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); @@ -178,7 +179,7 @@ static double Abs(int x) { SetGlobalProperty("x", Smi::FromInt(x)); bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); @@ -199,7 +200,7 @@ static double Sum(int n) { SetGlobalProperty("n", Smi::FromInt(n)); bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); @@ -220,7 +221,7 @@ TEST(Print) { Handle<JSFunction> fun = Compile(source); if (fun.is_null()) return; bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); } @@ -253,7 +254,7 @@ TEST(Stuff) { Handle<JSFunction> fun = Compile(source); CHECK(!fun.is_null()); bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); CHECK_EQ(511.0, GetGlobalProperty("r")->ToObjectChecked()->Number()); @@ -268,11 +269,12 @@ TEST(UncaughtThrow) { Handle<JSFunction> fun = Compile(source); CHECK(!fun.is_null()); bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Handle<Object> result = Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(has_pending_exception); - CHECK_EQ(42.0, Top::pending_exception()->ToObjectChecked()->Number()); + CHECK_EQ(42.0, Isolate::Current()->pending_exception()-> + ToObjectChecked()->Number()); } @@ -293,18 +295,18 @@ TEST(C2JSFrames) { // Run the generated code to populate the global object with 'foo'. bool has_pending_exception; - Handle<JSObject> global(Top::context()->global()); + Handle<JSObject> global(Isolate::Current()->context()->global()); Execution::Call(fun0, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); - Object* foo_symbol = Factory::LookupAsciiSymbol("foo")->ToObjectChecked(); - MaybeObject* fun1_object = - Top::context()->global()->GetProperty(String::cast(foo_symbol)); + Object* foo_symbol = FACTORY->LookupAsciiSymbol("foo")->ToObjectChecked(); + MaybeObject* fun1_object = Isolate::Current()->context()->global()-> + GetProperty(String::cast(foo_symbol)); Handle<Object> fun1(fun1_object->ToObjectChecked()); CHECK(fun1->IsJSFunction()); Object** argv[1] = { - Handle<Object>::cast(Factory::LookupAsciiSymbol("hello")).location() + Handle<Object>::cast(FACTORY->LookupAsciiSymbol("hello")).location() }; Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv, &has_pending_exception); @@ -318,8 +320,8 @@ TEST(Regression236) { InitializeVM(); v8::HandleScope scope; - Handle<Script> script = Factory::NewScript(Factory::empty_string()); - script->set_source(Heap::undefined_value()); + Handle<Script> script = FACTORY->NewScript(FACTORY->empty_string()); + script->set_source(HEAP->undefined_value()); CHECK_EQ(-1, GetScriptLineNumber(script, 0)); CHECK_EQ(-1, GetScriptLineNumber(script, 100)); CHECK_EQ(-1, GetScriptLineNumber(script, -1)); @@ -348,3 +350,51 @@ TEST(GetScriptLineNumber) { CHECK_EQ(i, f->GetScriptLineNumber()); } } + + +#ifdef ENABLE_DISASSEMBLER +static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, + const char* property_name) { + v8::Local<v8::Function> fun = + v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); + return v8::Utils::OpenHandle(*fun); +} + + +static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) { + // Create a disassembler with default name lookup. + disasm::NameConverter name_converter; + disasm::Disassembler d(name_converter); + + if (f->code()->kind() == Code::FUNCTION) { + Address pc = f->code()->instruction_start(); + int decode_size = + Min(f->code()->instruction_size(), + static_cast<int>(f->code()->stack_check_table_offset())); + Address end = pc + decode_size; + + v8::internal::EmbeddedVector<char, 128> decode_buffer; + while (pc < end) { + pc += d.InstructionDecode(decode_buffer, pc); + CHECK(strstr(decode_buffer.start(), "mov eax,0x178c29c") == NULL); + CHECK(strstr(decode_buffer.start(), "push 0x178c29c") == NULL); + CHECK(strstr(decode_buffer.start(), "0x178c29c") == NULL); + } + } +} + + +TEST(SplitConstantsInFullCompiler) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("function f() { a = 12345678 }; f();"); + CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f")); + CompileRun("function f(x) { a = 12345678 + x}; f(1);"); + CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f")); + CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);"); + CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f")); + CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);"); + CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f")); +} +#endif diff --git a/deps/v8/test/cctest/test-conversions.cc b/deps/v8/test/cctest/test-conversions.cc index 1b5cc2dee..7c29746fc 100644 --- a/deps/v8/test/cctest/test-conversions.cc +++ b/deps/v8/test/cctest/test-conversions.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #include <stdlib.h> @@ -11,139 +11,151 @@ using namespace v8::internal; TEST(Hex) { - CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX | ALLOW_OCTALS)); - - CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX)); - CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX)); - CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX)); - CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX)); - CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX)); - CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX)); + UnicodeCache uc; + CHECK_EQ(0.0, StringToDouble(&uc, "0x0", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0X0", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(1.0, StringToDouble(&uc, "0x1", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(16.0, StringToDouble(&uc, "0x10", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(255.0, StringToDouble(&uc, "0xff", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(175.0, StringToDouble(&uc, "0xAF", ALLOW_HEX | ALLOW_OCTALS)); + + CHECK_EQ(0.0, StringToDouble(&uc, "0x0", ALLOW_HEX)); + CHECK_EQ(0.0, StringToDouble(&uc, "0X0", ALLOW_HEX)); + CHECK_EQ(1.0, StringToDouble(&uc, "0x1", ALLOW_HEX)); + CHECK_EQ(16.0, StringToDouble(&uc, "0x10", ALLOW_HEX)); + CHECK_EQ(255.0, StringToDouble(&uc, "0xff", ALLOW_HEX)); + CHECK_EQ(175.0, StringToDouble(&uc, "0xAF", ALLOW_HEX)); } TEST(Octal) { - CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(8.0, StringToDouble("010", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(63.0, StringToDouble("077", ALLOW_HEX | ALLOW_OCTALS)); - - CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX)); - CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX)); - CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX)); - CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX)); - CHECK_EQ(10.0, StringToDouble("010", ALLOW_HEX)); - CHECK_EQ(77.0, StringToDouble("077", ALLOW_HEX)); + UnicodeCache uc; + CHECK_EQ(0.0, StringToDouble(&uc, "0", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "00", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(1.0, StringToDouble(&uc, "01", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(7.0, StringToDouble(&uc, "07", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(8.0, StringToDouble(&uc, "010", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(63.0, StringToDouble(&uc, "077", ALLOW_HEX | ALLOW_OCTALS)); + + CHECK_EQ(0.0, StringToDouble(&uc, "0", ALLOW_HEX)); + CHECK_EQ(0.0, StringToDouble(&uc, "00", ALLOW_HEX)); + CHECK_EQ(1.0, StringToDouble(&uc, "01", ALLOW_HEX)); + CHECK_EQ(7.0, StringToDouble(&uc, "07", ALLOW_HEX)); + CHECK_EQ(10.0, StringToDouble(&uc, "010", ALLOW_HEX)); + CHECK_EQ(77.0, StringToDouble(&uc, "077", ALLOW_HEX)); const double x = 010000000000; // Power of 2, no rounding errors. - CHECK_EQ(x * x * x * x * x, StringToDouble("01" "0000000000" "0000000000" + CHECK_EQ(x * x * x * x * x, StringToDouble(&uc, "01" "0000000000" "0000000000" "0000000000" "0000000000" "0000000000", ALLOW_OCTALS)); } TEST(MalformedOctal) { - CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX | ALLOW_OCTALS)); + UnicodeCache uc; + CHECK_EQ(8.0, StringToDouble(&uc, "08", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(81.0, StringToDouble(&uc, "081", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(78.0, StringToDouble(&uc, "078", ALLOW_HEX | ALLOW_OCTALS)); - CHECK(isnan(StringToDouble("07.7", ALLOW_HEX | ALLOW_OCTALS))); - CHECK(isnan(StringToDouble("07.8", ALLOW_HEX | ALLOW_OCTALS))); - CHECK(isnan(StringToDouble("07e8", ALLOW_HEX | ALLOW_OCTALS))); - CHECK(isnan(StringToDouble("07e7", ALLOW_HEX | ALLOW_OCTALS))); + CHECK(isnan(StringToDouble(&uc, "07.7", ALLOW_HEX | ALLOW_OCTALS))); + CHECK(isnan(StringToDouble(&uc, "07.8", ALLOW_HEX | ALLOW_OCTALS))); + CHECK(isnan(StringToDouble(&uc, "07e8", ALLOW_HEX | ALLOW_OCTALS))); + CHECK(isnan(StringToDouble(&uc, "07e7", ALLOW_HEX | ALLOW_OCTALS))); - CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(8.7, StringToDouble(&uc, "08.7", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(8e7, StringToDouble(&uc, "08e7", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.001, StringToDouble(&uc, "0.001", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.713, StringToDouble(&uc, "0.713", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX)); - CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX)); - CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX)); + CHECK_EQ(8.0, StringToDouble(&uc, "08", ALLOW_HEX)); + CHECK_EQ(81.0, StringToDouble(&uc, "081", ALLOW_HEX)); + CHECK_EQ(78.0, StringToDouble(&uc, "078", ALLOW_HEX)); - CHECK_EQ(7.7, StringToDouble("07.7", ALLOW_HEX)); - CHECK_EQ(7.8, StringToDouble("07.8", ALLOW_HEX)); - CHECK_EQ(7e8, StringToDouble("07e8", ALLOW_HEX)); - CHECK_EQ(7e7, StringToDouble("07e7", ALLOW_HEX)); + CHECK_EQ(7.7, StringToDouble(&uc, "07.7", ALLOW_HEX)); + CHECK_EQ(7.8, StringToDouble(&uc, "07.8", ALLOW_HEX)); + CHECK_EQ(7e8, StringToDouble(&uc, "07e8", ALLOW_HEX)); + CHECK_EQ(7e7, StringToDouble(&uc, "07e7", ALLOW_HEX)); - CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX)); - CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX)); + CHECK_EQ(8.7, StringToDouble(&uc, "08.7", ALLOW_HEX)); + CHECK_EQ(8e7, StringToDouble(&uc, "08e7", ALLOW_HEX)); - CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX)); - CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX)); + CHECK_EQ(0.001, StringToDouble(&uc, "0.001", ALLOW_HEX)); + CHECK_EQ(0.713, StringToDouble(&uc, "0.713", ALLOW_HEX)); } TEST(TrailingJunk) { - CHECK_EQ(8.0, StringToDouble("8q", ALLOW_TRAILING_JUNK)); - CHECK_EQ(63.0, StringToDouble("077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); - CHECK_EQ(10.0, StringToDouble("10e", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); - CHECK_EQ(10.0, StringToDouble("10e-", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); + UnicodeCache uc; + CHECK_EQ(8.0, StringToDouble(&uc, "8q", ALLOW_TRAILING_JUNK)); + CHECK_EQ(63.0, + StringToDouble(&uc, "077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); + CHECK_EQ(10.0, + StringToDouble(&uc, "10e", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); + CHECK_EQ(10.0, + StringToDouble(&uc, "10e-", ALLOW_OCTALS | ALLOW_TRAILING_JUNK)); } TEST(NonStrDecimalLiteral) { - CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value()))); - CHECK(isnan(StringToDouble("", NO_FLAGS, OS::nan_value()))); - CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value()))); - CHECK_EQ(0.0, StringToDouble("", NO_FLAGS)); - CHECK_EQ(0.0, StringToDouble(" ", NO_FLAGS)); + UnicodeCache uc; + CHECK(isnan(StringToDouble(&uc, " ", NO_FLAGS, OS::nan_value()))); + CHECK(isnan(StringToDouble(&uc, "", NO_FLAGS, OS::nan_value()))); + CHECK(isnan(StringToDouble(&uc, " ", NO_FLAGS, OS::nan_value()))); + CHECK_EQ(0.0, StringToDouble(&uc, "", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble(&uc, " ", NO_FLAGS)); } TEST(IntegerStrLiteral) { - CHECK_EQ(0.0, StringToDouble("0.0", NO_FLAGS)); - CHECK_EQ(0.0, StringToDouble("0", NO_FLAGS)); - CHECK_EQ(0.0, StringToDouble("00", NO_FLAGS)); - CHECK_EQ(0.0, StringToDouble("000", NO_FLAGS)); - CHECK_EQ(1.0, StringToDouble("1", NO_FLAGS)); - CHECK_EQ(-1.0, StringToDouble("-1", NO_FLAGS)); - CHECK_EQ(-1.0, StringToDouble(" -1 ", NO_FLAGS)); - CHECK_EQ(1.0, StringToDouble(" +1 ", NO_FLAGS)); - CHECK(isnan(StringToDouble(" - 1 ", NO_FLAGS))); - CHECK(isnan(StringToDouble(" + 1 ", NO_FLAGS))); - - CHECK_EQ(0.0, StringToDouble("0e0", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0e1", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0e-1", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0e-100000", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0e+100000", ALLOW_HEX | ALLOW_OCTALS)); - CHECK_EQ(0.0, StringToDouble("0.", ALLOW_HEX | ALLOW_OCTALS)); + UnicodeCache uc; + CHECK_EQ(0.0, StringToDouble(&uc, "0.0", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble(&uc, "00", NO_FLAGS)); + CHECK_EQ(0.0, StringToDouble(&uc, "000", NO_FLAGS)); + CHECK_EQ(1.0, StringToDouble(&uc, "1", NO_FLAGS)); + CHECK_EQ(-1.0, StringToDouble(&uc, "-1", NO_FLAGS)); + CHECK_EQ(-1.0, StringToDouble(&uc, " -1 ", NO_FLAGS)); + CHECK_EQ(1.0, StringToDouble(&uc, " +1 ", NO_FLAGS)); + CHECK(isnan(StringToDouble(&uc, " - 1 ", NO_FLAGS))); + CHECK(isnan(StringToDouble(&uc, " + 1 ", NO_FLAGS))); + + CHECK_EQ(0.0, StringToDouble(&uc, "0e0", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0e1", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0e-1", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0e-100000", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0e+100000", ALLOW_HEX | ALLOW_OCTALS)); + CHECK_EQ(0.0, StringToDouble(&uc, "0.", ALLOW_HEX | ALLOW_OCTALS)); } TEST(LongNumberStr) { - CHECK_EQ(1e10, StringToDouble("1" "0000000000", NO_FLAGS)); - CHECK_EQ(1e20, StringToDouble("1" "0000000000" "0000000000", NO_FLAGS)); + UnicodeCache uc; + CHECK_EQ(1e10, StringToDouble(&uc, "1" "0000000000", NO_FLAGS)); + CHECK_EQ(1e20, StringToDouble(&uc, "1" "0000000000" "0000000000", NO_FLAGS)); - CHECK_EQ(1e60, StringToDouble("1" "0000000000" "0000000000" "0000000000" + CHECK_EQ(1e60, StringToDouble(&uc, "1" "0000000000" "0000000000" "0000000000" "0000000000" "0000000000" "0000000000", NO_FLAGS)); - CHECK_EQ(1e-2, StringToDouble("." "0" "1", NO_FLAGS)); - CHECK_EQ(1e-11, StringToDouble("." "0000000000" "1", NO_FLAGS)); - CHECK_EQ(1e-21, StringToDouble("." "0000000000" "0000000000" "1", NO_FLAGS)); + CHECK_EQ(1e-2, StringToDouble(&uc, "." "0" "1", NO_FLAGS)); + CHECK_EQ(1e-11, StringToDouble(&uc, "." "0000000000" "1", NO_FLAGS)); + CHECK_EQ(1e-21, StringToDouble(&uc, "." "0000000000" "0000000000" "1", + NO_FLAGS)); - CHECK_EQ(1e-61, StringToDouble("." "0000000000" "0000000000" "0000000000" + CHECK_EQ(1e-61, StringToDouble(&uc, "." "0000000000" "0000000000" "0000000000" "0000000000" "0000000000" "0000000000" "1", NO_FLAGS)); // x = 24414062505131248.0 and y = 24414062505131252.0 are representable in // double. Check chat z = (x + y) / 2 is rounded to x... CHECK_EQ(24414062505131248.0, - StringToDouble("24414062505131250.0", NO_FLAGS)); + StringToDouble(&uc, "24414062505131250.0", NO_FLAGS)); // ... and z = (x + y) / 2 + delta is rounded to y. CHECK_EQ(24414062505131252.0, - StringToDouble("24414062505131250.000000001", NO_FLAGS)); + StringToDouble(&uc, "24414062505131250.000000001", NO_FLAGS)); } TEST(MaximumSignificantDigits) { + UnicodeCache uc; char num[] = "4.4501477170144020250819966727949918635852426585926051135169509" "122872622312493126406953054127118942431783801370080830523154578" @@ -159,15 +171,16 @@ TEST(MaximumSignificantDigits) { "847003580761626016356864581135848683152156368691976240370422601" "6998291015625000000000000000000000000000000000e-308"; - CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(num, NO_FLAGS)); + CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(&uc, num, NO_FLAGS)); // Changes the result of strtod (at least in glibc implementation). num[sizeof(num) - 8] = '1'; - CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(num, NO_FLAGS)); + CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(&uc, num, NO_FLAGS)); } TEST(MinimumExponent) { + UnicodeCache uc; // Same test but with different point-position. char num[] = "445014771701440202508199667279499186358524265859260511351695091" @@ -184,29 +197,31 @@ TEST(MinimumExponent) { "470035807616260163568645811358486831521563686919762403704226016" "998291015625000000000000000000000000000000000e-1108"; - CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(num, NO_FLAGS)); + CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(&uc, num, NO_FLAGS)); // Changes the result of strtod (at least in glibc implementation). num[sizeof(num) - 8] = '1'; - CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(num, NO_FLAGS)); + CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(&uc, num, NO_FLAGS)); } TEST(MaximumExponent) { + UnicodeCache uc; char num[] = "0.16e309"; - CHECK_EQ(1.59999999999999997765e+308, StringToDouble(num, NO_FLAGS)); + CHECK_EQ(1.59999999999999997765e+308, StringToDouble(&uc, num, NO_FLAGS)); } TEST(ExponentNumberStr) { - CHECK_EQ(1e1, StringToDouble("1e1", NO_FLAGS)); - CHECK_EQ(1e1, StringToDouble("1e+1", NO_FLAGS)); - CHECK_EQ(1e-1, StringToDouble("1e-1", NO_FLAGS)); - CHECK_EQ(1e100, StringToDouble("1e+100", NO_FLAGS)); - CHECK_EQ(1e-100, StringToDouble("1e-100", NO_FLAGS)); - CHECK_EQ(1e-106, StringToDouble(".000001e-100", NO_FLAGS)); + UnicodeCache uc; + CHECK_EQ(1e1, StringToDouble(&uc, "1e1", NO_FLAGS)); + CHECK_EQ(1e1, StringToDouble(&uc, "1e+1", NO_FLAGS)); + CHECK_EQ(1e-1, StringToDouble(&uc, "1e-1", NO_FLAGS)); + CHECK_EQ(1e100, StringToDouble(&uc, "1e+100", NO_FLAGS)); + CHECK_EQ(1e-100, StringToDouble(&uc, "1e-100", NO_FLAGS)); + CHECK_EQ(1e-106, StringToDouble(&uc, ".000001e-100", NO_FLAGS)); } class OneBit1: public BitField<uint32_t, 0, 1> {}; diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc index 7f06bc34d..7d898cedb 100644 --- a/deps/v8/test/cctest/test-cpu-profiler.cc +++ b/deps/v8/test/cctest/test-cpu-profiler.cc @@ -7,6 +7,7 @@ #include "v8.h" #include "cpu-profiler-inl.h" #include "cctest.h" +#include "../include/v8-profiler.h" namespace i = v8::internal; @@ -25,9 +26,6 @@ TEST(StartStop) { ProfileGenerator generator(&profiles); ProfilerEventsProcessor processor(&generator); processor.Start(); - while (!processor.running()) { - i::Thread::YieldCPU(); - } processor.Stop(); processor.Join(); } @@ -89,18 +87,15 @@ TEST(CodeEvents) { ProfileGenerator generator(&profiles); ProfilerEventsProcessor processor(&generator); processor.Start(); - while (!processor.running()) { - i::Thread::YieldCPU(); - } // Enqueue code creation events. i::HandleScope scope; const char* aaa_str = "aaa"; - i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii( + i::Handle<i::String> aaa_name = FACTORY->NewStringFromAscii( i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, *aaa_name, - i::Heap::empty_string(), + HEAP->empty_string(), 0, ToAddress(0x1000), 0x100, @@ -153,9 +148,6 @@ TEST(TickEvents) { ProfileGenerator generator(&profiles); ProfilerEventsProcessor processor(&generator); processor.Start(); - while (!processor.running()) { - i::Thread::YieldCPU(); - } processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, "bbb", @@ -236,4 +228,178 @@ TEST(CrashIfStoppingLastNonExistentProfile) { CpuProfiler::TearDown(); } + +// http://code.google.com/p/v8/issues/detail?id=1398 +// Long stacks (exceeding max frames limit) must not be erased. +TEST(Issue1398) { + TestSetup test_setup; + CpuProfilesCollection profiles; + profiles.StartProfiling("", 1); + ProfileGenerator generator(&profiles); + ProfilerEventsProcessor processor(&generator); + processor.Start(); + + processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, + "bbb", + ToAddress(0x1200), + 0x80); + + i::TickSample* sample = processor.TickSampleEvent(); + sample->pc = ToAddress(0x1200); + sample->tos = 0; + sample->frames_count = i::TickSample::kMaxFramesCount; + for (int i = 0; i < sample->frames_count; ++i) { + sample->stack[i] = ToAddress(0x1200); + } + + processor.Stop(); + processor.Join(); + CpuProfile* profile = + profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); + CHECK_NE(NULL, profile); + + int actual_depth = 0; + const ProfileNode* node = profile->top_down()->root(); + while (node->children()->length() > 0) { + node = node->children()->last(); + ++actual_depth; + } + + CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. +} + + +TEST(DeleteAllCpuProfiles) { + InitializeVM(); + TestSetup test_setup; + CpuProfiler::Setup(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + CpuProfiler::StartProfiling("1"); + CpuProfiler::StopProfiling("1"); + CHECK_EQ(1, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::StartProfiling("1"); + CpuProfiler::StartProfiling("2"); + CpuProfiler::StopProfiling("2"); + CpuProfiler::StopProfiling("1"); + CHECK_EQ(2, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + // Test profiling cancellation by the 'delete' command. + CpuProfiler::StartProfiling("1"); + CpuProfiler::StartProfiling("2"); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + CpuProfiler::TearDown(); +} + + +TEST(DeleteCpuProfile) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount()); + v8::Local<v8::String> name1 = v8::String::New("1"); + v8::CpuProfiler::StartProfiling(name1); + const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1); + CHECK_NE(NULL, p1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid1 = p1->GetUid(); + CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1)); + const_cast<v8::CpuProfile*>(p1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + + v8::Local<v8::String> name2 = v8::String::New("2"); + v8::CpuProfiler::StartProfiling(name2); + const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2); + CHECK_NE(NULL, p2); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid2 = p2->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); + CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + v8::Local<v8::String> name3 = v8::String::New("3"); + v8::CpuProfiler::StartProfiling(name3); + const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3); + CHECK_NE(NULL, p3); + CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount()); + unsigned uid3 = p3->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + const_cast<v8::CpuProfile*>(p2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast<v8::CpuProfile*>(p3)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); +} + + +TEST(DeleteCpuProfileDifferentTokens) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount()); + v8::Local<v8::String> name1 = v8::String::New("1"); + v8::CpuProfiler::StartProfiling(name1); + const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1); + CHECK_NE(NULL, p1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid1 = p1->GetUid(); + CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1)); + v8::Local<v8::String> token1 = v8::String::New("token1"); + const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1); + CHECK_NE(NULL, p1_t1); + CHECK_NE(p1, p1_t1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + const_cast<v8::CpuProfile*>(p1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1)); + const_cast<v8::CpuProfile*>(p1_t1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + v8::Local<v8::String> name2 = v8::String::New("2"); + v8::CpuProfiler::StartProfiling(name2); + v8::Local<v8::String> token2 = v8::String::New("token2"); + const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2); + CHECK_NE(NULL, p2_t2); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid2 = p2_t2->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); + const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2); + CHECK_NE(p2_t2, p2); + v8::Local<v8::String> name3 = v8::String::New("3"); + v8::CpuProfiler::StartProfiling(name3); + const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3); + CHECK_NE(NULL, p3); + CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount()); + unsigned uid3 = p3->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast<v8::CpuProfile*>(p2_t2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast<v8::CpuProfile*>(p2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast<v8::CpuProfile*>(p3)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3)); +} + #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/test/cctest/test-dataflow.cc b/deps/v8/test/cctest/test-dataflow.cc index 5894de2a8..ad48f5503 100644 --- a/deps/v8/test/cctest/test-dataflow.cc +++ b/deps/v8/test/cctest/test-dataflow.cc @@ -35,7 +35,8 @@ using namespace v8::internal; TEST(BitVector) { - ZoneScope zone(DELETE_ON_EXIT); + v8::internal::V8::Initialize(NULL); + ZoneScope zone(Isolate::Current(), DELETE_ON_EXIT); { BitVector v(15); v.Add(1); diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 7245e54be..4886a8a07 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -1,4 +1,4 @@ -// Copyright 2010 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: @@ -143,17 +143,18 @@ class DebugLocalContext { inline v8::Context* operator*() { return *context_; } inline bool IsReady() { return !context_.IsEmpty(); } void ExposeDebug() { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // Expose the debug context global object in the global object for testing. - Debug::Load(); - Debug::debug_context()->set_security_token( + debug->Load(); + debug->debug_context()->set_security_token( v8::Utils::OpenHandle(*context_)->security_token()); Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast( v8::Utils::OpenHandle(*context_->Global()))); Handle<v8::internal::String> debug_string = - v8::internal::Factory::LookupAsciiSymbol("debug"); + FACTORY->LookupAsciiSymbol("debug"); SetProperty(global, debug_string, - Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM, + Handle<Object>(debug->debug_context()->global_proxy()), DONT_ENUM, ::v8::internal::kNonStrictMode); } private: @@ -196,7 +197,8 @@ static bool HasDebugInfo(v8::Handle<v8::Function> fun) { static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) { static int break_point = 0; Handle<v8::internal::SharedFunctionInfo> shared(fun->shared()); - Debug::SetBreakPoint( + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + debug->SetBreakPoint( shared, Handle<Object>(v8::internal::Smi::FromInt(++break_point)), &position); @@ -279,7 +281,8 @@ static int SetScriptBreakPointByNameFromJS(const char* script_name, // Clear a break point. static void ClearBreakPoint(int break_point) { - Debug::ClearBreakPoint( + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + debug->ClearBreakPoint( Handle<Object>(v8::internal::Smi::FromInt(break_point))); } @@ -339,8 +342,9 @@ static void ChangeScriptBreakPointIgnoreCountFromJS(int break_point_number, // Change break on exception. static void ChangeBreakOnException(bool caught, bool uncaught) { - Debug::ChangeBreakOnException(v8::internal::BreakException, caught); - Debug::ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught); + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + debug->ChangeBreakOnException(v8::internal::BreakException, caught); + debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught); } @@ -365,7 +369,8 @@ static void ChangeBreakOnExceptionFromJS(bool caught, bool uncaught) { // Prepare to step to next break location. static void PrepareStep(StepAction step_action) { - Debug::PrepareStep(step_action, 1); + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + debug->PrepareStep(step_action, 1); } @@ -376,7 +381,9 @@ namespace internal { // Collect the currently debugged functions. Handle<FixedArray> GetDebuggedFunctions() { - v8::internal::DebugInfoListNode* node = Debug::debug_info_list_; + Debug* debug = Isolate::Current()->debug(); + + v8::internal::DebugInfoListNode* node = debug->debug_info_list_; // Find the number of debugged functions. int count = 0; @@ -387,7 +394,7 @@ Handle<FixedArray> GetDebuggedFunctions() { // Allocate array for the debugged functions Handle<FixedArray> debugged_functions = - v8::internal::Factory::NewFixedArray(count); + FACTORY->NewFixedArray(count); // Run through the debug info objects and collect all functions. count = 0; @@ -402,7 +409,9 @@ Handle<FixedArray> GetDebuggedFunctions() { static Handle<Code> ComputeCallDebugBreak(int argc) { CALL_HEAP_FUNCTION( - v8::internal::StubCache::ComputeCallDebugBreak(argc, Code::CALL_IC), + v8::internal::Isolate::Current(), + v8::internal::Isolate::Current()->stub_cache()->ComputeCallDebugBreak( + argc, Code::CALL_IC), Code); } @@ -411,12 +420,12 @@ static Handle<Code> ComputeCallDebugBreak(int argc) { void CheckDebuggerUnloaded(bool check_functions) { // Check that the debugger context is cleared and that there is no debug // information stored for the debugger. - CHECK(Debug::debug_context().is_null()); - CHECK_EQ(NULL, Debug::debug_info_list_); + CHECK(Isolate::Current()->debug()->debug_context().is_null()); + 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(false); + HEAP->CollectAllGarbage(false); // Iterate the head and check that there are no debugger related objects left. HeapIterator iterator; @@ -444,8 +453,8 @@ void CheckDebuggerUnloaded(bool check_functions) { void ForceUnloadDebugger() { - Debugger::never_unload_debugger_ = false; - Debugger::UnloadDebugger(); + Isolate::Current()->debugger()->never_unload_debugger_ = false; + Isolate::Current()->debugger()->UnloadDebugger(); } @@ -480,6 +489,8 @@ void CheckDebugBreakFunction(DebugLocalContext* env, const char* source, const char* name, int position, v8::internal::RelocInfo::Mode mode, Code* debug_break) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + // Create function and set the break point. Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle( *CompileFunction(env, source, name)); @@ -490,7 +501,11 @@ void CheckDebugBreakFunction(DebugLocalContext* env, CHECK(Debug::HasDebugInfo(shared)); TestBreakLocationIterator it1(Debug::GetDebugInfo(shared)); it1.FindBreakLocationFromPosition(position); - CHECK_EQ(mode, it1.it()->rinfo()->rmode()); + v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode(); + if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) { + actual_mode = v8::internal::RelocInfo::CODE_TARGET; + } + CHECK_EQ(mode, actual_mode); if (mode != v8::internal::RelocInfo::JS_RETURN) { CHECK_EQ(debug_break, Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address())); @@ -501,11 +516,15 @@ void CheckDebugBreakFunction(DebugLocalContext* env, // Clear the break point and check that the debug break function is no longer // there ClearBreakPoint(bp); - CHECK(!Debug::HasDebugInfo(shared)); - CHECK(Debug::EnsureDebugInfo(shared)); + CHECK(!debug->HasDebugInfo(shared)); + CHECK(debug->EnsureDebugInfo(shared)); TestBreakLocationIterator it2(Debug::GetDebugInfo(shared)); it2.FindBreakLocationFromPosition(position); - CHECK_EQ(mode, it2.it()->rinfo()->rmode()); + actual_mode = it2.it()->rinfo()->rmode(); + if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) { + actual_mode = v8::internal::RelocInfo::CODE_TARGET; + } + CHECK_EQ(mode, actual_mode); if (mode == v8::internal::RelocInfo::JS_RETURN) { CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo())); } @@ -634,8 +653,9 @@ static void DebugEventBreakPointHitCount(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); // Count the number of breaks. if (event == v8::Break) { @@ -738,8 +758,10 @@ static void DebugEventCounter(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); + // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); // Count the number of breaks. if (event == v8::Break) { @@ -796,8 +818,9 @@ static void DebugEventEvaluate(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { for (int i = 0; checks[i].expr != NULL; i++) { @@ -822,8 +845,9 @@ static void DebugEventRemoveBreakPoint(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { break_point_hit_count++; @@ -840,8 +864,9 @@ static void DebugEventStep(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { break_point_hit_count++; @@ -866,8 +891,9 @@ static void DebugEventStepSequence(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break || event == v8::Exception) { // Check that the current function is the expected. @@ -896,8 +922,9 @@ static void DebugEventBreakPointCollectGarbage( v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); // Perform a garbage collection when break point is hit and continue. Based // on the number of break points hit either scavenge or mark compact @@ -906,10 +933,10 @@ static void DebugEventBreakPointCollectGarbage( break_point_hit_count++; if (break_point_hit_count % 2 == 0) { // Scavenge. - Heap::CollectGarbage(v8::internal::NEW_SPACE); + HEAP->CollectGarbage(v8::internal::NEW_SPACE); } else { // Mark sweep compact. - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); } } } @@ -921,8 +948,9 @@ static void DebugEventBreak(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { // Count the number of breaks. @@ -930,7 +958,7 @@ static void DebugEventBreak(v8::DebugEvent event, // Run the garbage collector to enforce heap verification if option // --verify-heap is set. - Heap::CollectGarbage(v8::internal::NEW_SPACE); + HEAP->CollectGarbage(v8::internal::NEW_SPACE); // Set the break flag again to come back here as soon as possible. v8::Debug::DebugBreak(); @@ -946,8 +974,9 @@ static void DebugEventBreakMax(v8::DebugEvent event, v8::Handle<v8::Object> exec_state, v8::Handle<v8::Object> event_data, v8::Handle<v8::Value> data) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. - CHECK_NE(v8::internal::Debug::break_id(), 0); + CHECK_NE(debug->break_id(), 0); if (event == v8::Break) { if (break_point_hit_count < max_break_point_hit_count) { @@ -987,6 +1016,7 @@ static void MessageCallbackCount(v8::Handle<v8::Message> message, // of break locations. TEST(DebugStub) { using ::v8::internal::Builtins; + using ::v8::internal::Isolate; v8::HandleScope scope; DebugLocalContext env; @@ -999,12 +1029,14 @@ TEST(DebugStub) { "function f2(){x=1;}", "f2", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, - Builtins::builtin(Builtins::StoreIC_DebugBreak)); + Isolate::Current()->builtins()->builtin( + Builtins::kStoreIC_DebugBreak)); CheckDebugBreakFunction(&env, "function f3(){var a=x;}", "f3", 0, v8::internal::RelocInfo::CODE_TARGET_CONTEXT, - Builtins::builtin(Builtins::LoadIC_DebugBreak)); + Isolate::Current()->builtins()->builtin( + Builtins::kLoadIC_DebugBreak)); // TODO(1240753): Make the test architecture independent or split // parts of the debugger into architecture dependent files. This @@ -1017,14 +1049,16 @@ TEST(DebugStub) { "f4", 0, v8::internal::RelocInfo::CODE_TARGET, - Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak)); + Isolate::Current()->builtins()->builtin( + Builtins::kKeyedStoreIC_DebugBreak)); CheckDebugBreakFunction( &env, "function f5(){var index='propertyName'; var a={}; return a[index];}", "f5", 0, v8::internal::RelocInfo::CODE_TARGET, - Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak)); + Isolate::Current()->builtins()->builtin( + Builtins::kKeyedLoadIC_DebugBreak)); #endif // Check the debug break code stubs for call ICs with different number of @@ -1139,7 +1173,7 @@ TEST(BreakPointICLoad) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); - // Run with breakpoint + // Run with breakpoint. int bp = SetBreakPoint(foo, 0); foo->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); @@ -1172,7 +1206,7 @@ TEST(BreakPointICCall) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); - // Run with breakpoint. + // Run with breakpoint int bp = SetBreakPoint(foo, 0); foo->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); @@ -1367,12 +1401,12 @@ static void CallAndGC(v8::Local<v8::Object> recv, CHECK_EQ(1 + i * 3, break_point_hit_count); // Scavenge and call function. - Heap::CollectGarbage(v8::internal::NEW_SPACE); + HEAP->CollectGarbage(v8::internal::NEW_SPACE); f->Call(recv, 0, NULL); CHECK_EQ(2 + i * 3, break_point_hit_count); // Mark sweep (and perhaps compact) and call function. - Heap::CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(force_compaction); f->Call(recv, 0, NULL); CHECK_EQ(3 + i * 3, break_point_hit_count); } @@ -2199,7 +2233,7 @@ TEST(ScriptBreakPointLineTopLevel) { } f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); - Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); SetScriptBreakPointByNameFromJS("test.html", 3, -1); @@ -3698,7 +3732,7 @@ TEST(BreakOnException) { DebugLocalContext env; env.ExposeDebug(); - v8::internal::Top::TraceException(false); + v8::internal::Isolate::Current()->TraceException(false); // Create functions for testing break on exception. v8::Local<v8::Function> throws = @@ -3845,7 +3879,7 @@ TEST(BreakOnCompileException) { // For this test, we want to break on uncaught exceptions: ChangeBreakOnException(false, true); - v8::internal::Top::TraceException(false); + v8::internal::Isolate::Current()->TraceException(false); // Create a function for checking the function when hitting a break point. frame_count = CompileFunction(&env, frame_count_source, "frame_count"); @@ -4230,9 +4264,9 @@ TEST(InterceptorPropertyMirror) { "named_values[%d] instanceof debug.PropertyMirror", i); CHECK(CompileRun(buffer.start())->BooleanValue()); - // 4 is PropertyType.Interceptor + // 5 is PropertyType.Interceptor OS::SNPrintF(buffer, "named_values[%d].propertyType()", i); - CHECK_EQ(4, CompileRun(buffer.start())->Int32Value()); + CHECK_EQ(5, CompileRun(buffer.start())->Int32Value()); OS::SNPrintF(buffer, "named_values[%d].isNative()", i); CHECK(CompileRun(buffer.start())->BooleanValue()); @@ -4694,6 +4728,8 @@ Barriers message_queue_barriers; // placing JSON debugger commands in the queue. class MessageQueueDebuggerThread : public v8::internal::Thread { public: + MessageQueueDebuggerThread() + : Thread("MessageQueueDebuggerThread") { } void Run(); }; @@ -4793,10 +4829,11 @@ void MessageQueueDebuggerThread::Run() { // Main thread continues running source_3 to end, waits for this thread. } -MessageQueueDebuggerThread message_queue_debugger_thread; // This thread runs the v8 engine. TEST(MessageQueues) { + MessageQueueDebuggerThread message_queue_debugger_thread; + // Create a V8 environment v8::HandleScope scope; DebugLocalContext env; @@ -4942,11 +4979,13 @@ Barriers threaded_debugging_barriers; class V8Thread : public v8::internal::Thread { public: + V8Thread() : Thread("V8Thread") { } void Run(); }; class DebuggerThread : public v8::internal::Thread { public: + DebuggerThread() : Thread("DebuggerThread") { } void Run(); }; @@ -4990,6 +5029,7 @@ void V8Thread::Run() { "\n" "foo();\n"; + v8::V8::Initialize(); v8::HandleScope scope; DebugLocalContext env; v8::Debug::SetMessageHandler2(&ThreadedMessageHandler); @@ -5021,10 +5061,11 @@ void DebuggerThread::Run() { v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer)); } -DebuggerThread debugger_thread; -V8Thread v8_thread; TEST(ThreadedDebugging) { + DebuggerThread debugger_thread; + V8Thread v8_thread; + // Create a V8 environment threaded_debugging_barriers.Initialize(); @@ -5044,13 +5085,15 @@ TEST(ThreadedDebugging) { class BreakpointsV8Thread : public v8::internal::Thread { public: + BreakpointsV8Thread() : Thread("BreakpointsV8Thread") { } void Run(); }; class BreakpointsDebuggerThread : public v8::internal::Thread { public: explicit BreakpointsDebuggerThread(bool global_evaluate) - : global_evaluate_(global_evaluate) {} + : Thread("BreakpointsDebuggerThread"), + global_evaluate_(global_evaluate) {} void Run(); private: @@ -5099,6 +5142,7 @@ void BreakpointsV8Thread::Run() { const char* source_2 = "cat(17);\n" "cat(19);\n"; + v8::V8::Initialize(); v8::HandleScope scope; DebugLocalContext env; v8::Debug::SetMessageHandler2(&BreakpointsMessageHandler); @@ -5609,11 +5653,13 @@ TEST(DebuggerClearMessageHandlerWhileActive) { class HostDispatchV8Thread : public v8::internal::Thread { public: + HostDispatchV8Thread() : Thread("HostDispatchV8Thread") { } void Run(); }; class HostDispatchDebuggerThread : public v8::internal::Thread { public: + HostDispatchDebuggerThread() : Thread("HostDispatchDebuggerThread") { } void Run(); }; @@ -5643,6 +5689,7 @@ void HostDispatchV8Thread::Run() { "\n"; const char* source_2 = "cat(17);\n"; + v8::V8::Initialize(); v8::HandleScope scope; DebugLocalContext env; @@ -5683,11 +5730,10 @@ void HostDispatchDebuggerThread::Run() { v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer)); } -HostDispatchDebuggerThread host_dispatch_debugger_thread; -HostDispatchV8Thread host_dispatch_v8_thread; - TEST(DebuggerHostDispatch) { + HostDispatchDebuggerThread host_dispatch_debugger_thread; + HostDispatchV8Thread host_dispatch_v8_thread; i::FLAG_debugger_auto_break = true; // Create a V8 environment @@ -5711,11 +5757,14 @@ TEST(DebuggerHostDispatch) { class DebugMessageDispatchV8Thread : public v8::internal::Thread { public: + DebugMessageDispatchV8Thread() : Thread("DebugMessageDispatchV8Thread") { } void Run(); }; class DebugMessageDispatchDebuggerThread : public v8::internal::Thread { public: + DebugMessageDispatchDebuggerThread() + : Thread("DebugMessageDispatchDebuggerThread") { } void Run(); }; @@ -5728,6 +5777,7 @@ static void DebugMessageHandler() { void DebugMessageDispatchV8Thread::Run() { + v8::V8::Initialize(); v8::HandleScope scope; DebugLocalContext env; @@ -5747,11 +5797,11 @@ void DebugMessageDispatchDebuggerThread::Run() { debug_message_dispatch_barriers->barrier_2.Wait(); } -DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread; -DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread; - TEST(DebuggerDebugMessageDispatch) { + DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread; + DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread; + i::FLAG_debugger_auto_break = true; // Create a V8 environment @@ -5769,6 +5819,7 @@ TEST(DebuggerDebugMessageDispatch) { TEST(DebuggerAgent) { + i::Debugger* debugger = i::Isolate::Current()->debugger(); // Make sure these ports is not used by other tests to allow tests to run in // parallel. const int kPort1 = 5858; @@ -5786,18 +5837,23 @@ TEST(DebuggerAgent) { i::Socket::Setup(); // Test starting and stopping the agent without any client connection. - i::Debugger::StartAgent("test", kPort1); - i::Debugger::StopAgent(); - + debugger->StartAgent("test", kPort1); + debugger->StopAgent(); // Test starting the agent, connecting a client and shutting down the agent // with the client connected. - ok = i::Debugger::StartAgent("test", kPort2); + ok = debugger->StartAgent("test", kPort2); CHECK(ok); - i::Debugger::WaitForAgent(); + debugger->WaitForAgent(); i::Socket* client = i::OS::CreateSocket(); ok = client->Connect("localhost", port2_str); CHECK(ok); - i::Debugger::StopAgent(); + // It is important to wait for a message from the agent. Otherwise, + // we can close the server socket during "accept" syscall, making it failing + // (at least on Linux), and the test will work incorrectly. + char buf; + ok = client->Receive(&buf, 1) == 1; + CHECK(ok); + debugger->StopAgent(); delete client; // Test starting and stopping the agent with the required port already @@ -5805,8 +5861,8 @@ TEST(DebuggerAgent) { i::Socket* server = i::OS::CreateSocket(); server->Bind(kPort3); - i::Debugger::StartAgent("test", kPort3); - i::Debugger::StopAgent(); + debugger->StartAgent("test", kPort3); + debugger->StopAgent(); delete server; } @@ -5815,7 +5871,10 @@ TEST(DebuggerAgent) { class DebuggerAgentProtocolServerThread : public i::Thread { public: explicit DebuggerAgentProtocolServerThread(int port) - : port_(port), server_(NULL), client_(NULL), + : Thread("DebuggerAgentProtocolServerThread"), + port_(port), + server_(NULL), + client_(NULL), listening_(OS::CreateSemaphore(0)) { } ~DebuggerAgentProtocolServerThread() { @@ -6251,8 +6310,7 @@ static void ExecuteScriptForContextCheck() { v8::Persistent<v8::Context> context_1; v8::Handle<v8::ObjectTemplate> global_template = v8::Handle<v8::ObjectTemplate>(); - v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>(); - context_1 = v8::Context::New(NULL, global_template, global_object); + context_1 = v8::Context::New(NULL, global_template); // Default data value is undefined. CHECK(context_1->GetData()->IsUndefined()); @@ -6317,11 +6375,11 @@ static void DebugEvalContextCheckMessageHandler( const int kBufferSize = 1000; uint16_t buffer[kBufferSize]; const char* eval_command = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "arguments:{\"expression\":\"debugger;\"," - "\"global\":true,\"disable_break\":false}}"; + "{\"seq\":0," + "\"type\":\"request\"," + "\"command\":\"evaluate\"," + "\"arguments\":{\"expression\":\"debugger;\"," + "\"global\":true,\"disable_break\":false}}"; // Send evaluate command. v8::Debug::SendCommand(buffer, AsciiToUtf16(eval_command, buffer)); @@ -6376,17 +6434,18 @@ static void DebugEventScriptCollectedEvent(v8::DebugEvent event, // Test that scripts collected are reported through the debug event listener. TEST(ScriptCollectedEvent) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); break_point_hit_count = 0; script_collected_count = 0; v8::HandleScope scope; DebugLocalContext env; // Request the loaded scripts to initialize the debugger script cache. - Debug::GetLoadedScripts(); + debug->GetLoadedScripts(); // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); script_collected_count = 0; v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, @@ -6398,7 +6457,7 @@ TEST(ScriptCollectedEvent) { // Do garbage collection to collect the script above which is no longer // referenced. - Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(2, script_collected_count); @@ -6422,6 +6481,7 @@ static void ScriptCollectedMessageHandler(const v8::Debug::Message& message) { // Test that GetEventContext doesn't fail and return empty handle for // ScriptCollected events. TEST(ScriptCollectedEventContext) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); script_collected_message_count = 0; v8::HandleScope scope; @@ -6429,11 +6489,11 @@ TEST(ScriptCollectedEventContext) { DebugLocalContext env; // Request the loaded scripts to initialize the debugger script cache. - Debug::GetLoadedScripts(); + debug->GetLoadedScripts(); // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler); { @@ -6444,7 +6504,7 @@ TEST(ScriptCollectedEventContext) { // Do garbage collection to collect the script above which is no longer // referenced. - Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); CHECK_EQ(2, script_collected_message_count); @@ -6592,6 +6652,7 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { static void BreakMessageHandler(const v8::Debug::Message& message) { + i::Isolate* isolate = i::Isolate::Current(); if (message.IsEvent() && message.GetEvent() == v8::Break) { // Count the number of breaks. break_point_hit_count++; @@ -6603,18 +6664,18 @@ static void BreakMessageHandler(const v8::Debug::Message& message) { } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { v8::HandleScope scope; - bool is_debug_break = i::StackGuard::IsDebugBreak(); + bool is_debug_break = isolate->stack_guard()->IsDebugBreak(); // Force DebugBreak flag while serializer is working. - i::StackGuard::DebugBreak(); + isolate->stack_guard()->DebugBreak(); // Force serialization to trigger some internal JS execution. v8::Handle<v8::String> json = message.GetJSON(); // Restore previous state. if (is_debug_break) { - i::StackGuard::DebugBreak(); + isolate->stack_guard()->DebugBreak(); } else { - i::StackGuard::Continue(i::DEBUGBREAK); + isolate->stack_guard()->Continue(i::DEBUGBREAK); } } } @@ -6843,6 +6904,7 @@ static void DebugEventGetAtgumentPropertyValue( TEST(CallingContextIsNotDebugContext) { + v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // Create and enter a debugee context. v8::HandleScope scope; DebugLocalContext env; @@ -6851,7 +6913,7 @@ TEST(CallingContextIsNotDebugContext) { // Save handles to the debugger and debugee contexts to be used in // NamedGetterWithCallingContextCheck. debugee_context = v8::Local<v8::Context>(*env); - debugger_context = v8::Utils::ToLocal(Debug::debug_context()); + debugger_context = v8::Utils::ToLocal(debug->debug_context()); // Create object with 'a' property accessor. v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(); diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc index 6ea4c849e..619839185 100644 --- a/deps/v8/test/cctest/test-decls.cc +++ b/deps/v8/test/cctest/test-decls.cc @@ -130,7 +130,7 @@ void DeclarationContext::Check(const char* source, InitializeIfNeeded(); // A retry after a GC may pollute the counts, so perform gc now // to avoid that. - v8::internal::Heap::CollectGarbage(v8::internal::NEW_SPACE); + HEAP->CollectGarbage(v8::internal::NEW_SPACE); HandleScope scope; TryCatch catcher; catcher.SetVerbose(true); diff --git a/deps/v8/test/cctest/test-deoptimization.cc b/deps/v8/test/cctest/test-deoptimization.cc index 17453552e..056c98184 100644 --- a/deps/v8/test/cctest/test-deoptimization.cc +++ b/deps/v8/test/cctest/test-deoptimization.cc @@ -30,20 +30,21 @@ #include "v8.h" #include "api.h" +#include "cctest.h" #include "compilation-cache.h" #include "debug.h" #include "deoptimizer.h" +#include "isolate.h" #include "platform.h" #include "stub-cache.h" -#include "cctest.h" - -using ::v8::internal::Handle; -using ::v8::internal::Object; -using ::v8::internal::JSFunction; using ::v8::internal::Deoptimizer; using ::v8::internal::EmbeddedVector; +using ::v8::internal::Handle; +using ::v8::internal::Isolate; +using ::v8::internal::JSFunction; using ::v8::internal::OS; +using ::v8::internal::Object; // Size of temp buffer for formatting small strings. #define SMALL_STRING_BUFFER_SIZE 80 @@ -96,8 +97,8 @@ class AllowNativesSyntaxNoInlining { }; -Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, - const char* property_name) { +static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, + const char* property_name) { v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); return v8::Utils::OpenHandle(*fun); @@ -124,7 +125,7 @@ TEST(DeoptimizeSimple) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); // Test lazy deoptimization of a simple function. Call the function after the // deoptimization while it is still activated further down the stack. @@ -140,7 +141,7 @@ TEST(DeoptimizeSimple) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -164,7 +165,7 @@ TEST(DeoptimizeSimpleWithArguments) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); // Test lazy deoptimization of a simple function with some arguments. Call the // function after the deoptimization while it is still activated further down @@ -181,7 +182,7 @@ TEST(DeoptimizeSimpleWithArguments) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -207,7 +208,7 @@ TEST(DeoptimizeSimpleNested) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } } @@ -232,7 +233,7 @@ TEST(DeoptimizeRecursive) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); @@ -266,7 +267,7 @@ TEST(DeoptimizeMultiple) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -289,7 +290,7 @@ TEST(DeoptimizeConstructor) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(env->Global()->Get(v8_str("result"))->IsTrue()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); { AlwaysOptimizeAllowNativesSyntaxNoInlining options; @@ -306,7 +307,7 @@ TEST(DeoptimizeConstructor) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -337,7 +338,7 @@ TEST(DeoptimizeConstructorMultiple) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -385,7 +386,7 @@ TEST(DeoptimizeBinaryOperationADDString) { CHECK(result->IsString()); v8::String::AsciiValue ascii(result); CHECK_EQ("a+an X", *ascii); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -444,7 +445,7 @@ TEST(DeoptimizeBinaryOperationADD) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -458,7 +459,7 @@ TEST(DeoptimizeBinaryOperationSUB) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -472,7 +473,7 @@ TEST(DeoptimizeBinaryOperationMUL) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -486,7 +487,7 @@ TEST(DeoptimizeBinaryOperationDIV) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -500,7 +501,7 @@ TEST(DeoptimizeBinaryOperationMOD) { CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -545,7 +546,7 @@ TEST(DeoptimizeCompare) { CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -627,7 +628,7 @@ TEST(DeoptimizeLoadICStoreIC) { CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } @@ -710,5 +711,5 @@ TEST(DeoptimizeLoadICStoreICNested) { CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); - CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount()); + CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current())); } diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc index dea0db92c..032e6bc0f 100644 --- a/deps/v8/test/cctest/test-disasm-arm.cc +++ b/deps/v8/test/cctest/test-disasm-arm.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,11 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { // Setup 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() \ - InitializeVM(); \ - v8::HandleScope scope; \ +#define SETUP() \ + InitializeVM(); \ + v8::HandleScope scope; \ byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ - Assembler assm(buffer, 4*1024); \ + Assembler assm(Isolate::Current(), buffer, 4*1024); \ bool failure = false; @@ -436,9 +436,14 @@ TEST(Vfp) { "ee0faa90 vmov s31, r10"); COMPARE(vabs(d0, d1), - "eeb00bc1 vabs d0, d1"); + "eeb00bc1 vabs.f64 d0, d1"); COMPARE(vabs(d3, d4, mi), - "4eb03bc4 vabsmi d3, d4"); + "4eb03bc4 vabs.f64mi d3, d4"); + + COMPARE(vneg(d0, d1), + "eeb10b41 vneg.f64 d0, d1"); + COMPARE(vneg(d3, d4, mi), + "4eb13b44 vneg.f64mi d3, d4"); COMPARE(vadd(d0, d1, d2), "ee310b02 vadd.f64 d0, d1, d2"); @@ -517,7 +522,227 @@ TEST(Vfp) { "aef1aa10 vmrsge r10, FPSCR"); COMPARE(vmrs(pc), "eef1fa10 vmrs APSR, FPSCR"); + + COMPARE(vstm(ia, r0, d1, d3), + "ec801b06 vstmia r0, {d1-d3}"); + COMPARE(vldm(ia, r1, d2, d5), + "ec912b08 vldmia r1, {d2-d5}"); + COMPARE(vstm(ia, r2, d0, d15), + "ec820b20 vstmia r2, {d0-d15}"); + COMPARE(vldm(ia, r3, d0, d15), + "ec930b20 vldmia r3, {d0-d15}"); + COMPARE(vstm(ia, r4, s1, s3), + "ecc40a03 vstmia r4, {s1-s3}"); + COMPARE(vldm(ia, r5, s2, s5), + "ec951a04 vldmia r5, {s2-s5}"); + COMPARE(vstm(ia, r6, s0, s31), + "ec860a20 vstmia r6, {s0-s31}"); + COMPARE(vldm(ia, r7, s0, s31), + "ec970a20 vldmia r7, {s0-s31}"); } VERIFY_RUN(); } + + +TEST(LoadStore) { + SETUP(); + + COMPARE(ldrb(r0, MemOperand(r1)), + "e5d10000 ldrb r0, [r1, #+0]"); + COMPARE(ldrb(r2, MemOperand(r3, 42)), + "e5d3202a ldrb r2, [r3, #+42]"); + COMPARE(ldrb(r4, MemOperand(r5, -42)), + "e555402a ldrb r4, [r5, #-42]"); + COMPARE(ldrb(r6, MemOperand(r7, 42, PostIndex)), + "e4d7602a ldrb r6, [r7], #+42"); + COMPARE(ldrb(r8, MemOperand(r9, -42, PostIndex)), + "e459802a ldrb r8, [r9], #-42"); + COMPARE(ldrb(r10, MemOperand(fp, 42, PreIndex)), + "e5fba02a ldrb r10, [fp, #+42]!"); + COMPARE(ldrb(ip, MemOperand(sp, -42, PreIndex)), + "e57dc02a ldrb ip, [sp, #-42]!"); + COMPARE(ldrb(r0, MemOperand(r1, r2)), + "e7d10002 ldrb r0, [r1, +r2]"); + COMPARE(ldrb(r0, MemOperand(r1, r2, NegOffset)), + "e7510002 ldrb r0, [r1, -r2]"); + COMPARE(ldrb(r0, MemOperand(r1, r2, PostIndex)), + "e6d10002 ldrb r0, [r1], +r2"); + COMPARE(ldrb(r0, MemOperand(r1, r2, NegPostIndex)), + "e6510002 ldrb r0, [r1], -r2"); + COMPARE(ldrb(r0, MemOperand(r1, r2, PreIndex)), + "e7f10002 ldrb r0, [r1, +r2]!"); + COMPARE(ldrb(r0, MemOperand(r1, r2, NegPreIndex)), + "e7710002 ldrb r0, [r1, -r2]!"); + + COMPARE(strb(r0, MemOperand(r1)), + "e5c10000 strb r0, [r1, #+0]"); + COMPARE(strb(r2, MemOperand(r3, 42)), + "e5c3202a strb r2, [r3, #+42]"); + COMPARE(strb(r4, MemOperand(r5, -42)), + "e545402a strb r4, [r5, #-42]"); + COMPARE(strb(r6, MemOperand(r7, 42, PostIndex)), + "e4c7602a strb r6, [r7], #+42"); + COMPARE(strb(r8, MemOperand(r9, -42, PostIndex)), + "e449802a strb r8, [r9], #-42"); + COMPARE(strb(r10, MemOperand(fp, 42, PreIndex)), + "e5eba02a strb r10, [fp, #+42]!"); + COMPARE(strb(ip, MemOperand(sp, -42, PreIndex)), + "e56dc02a strb ip, [sp, #-42]!"); + COMPARE(strb(r0, MemOperand(r1, r2)), + "e7c10002 strb r0, [r1, +r2]"); + COMPARE(strb(r0, MemOperand(r1, r2, NegOffset)), + "e7410002 strb r0, [r1, -r2]"); + COMPARE(strb(r0, MemOperand(r1, r2, PostIndex)), + "e6c10002 strb r0, [r1], +r2"); + COMPARE(strb(r0, MemOperand(r1, r2, NegPostIndex)), + "e6410002 strb r0, [r1], -r2"); + COMPARE(strb(r0, MemOperand(r1, r2, PreIndex)), + "e7e10002 strb r0, [r1, +r2]!"); + COMPARE(strb(r0, MemOperand(r1, r2, NegPreIndex)), + "e7610002 strb r0, [r1, -r2]!"); + + COMPARE(ldrh(r0, MemOperand(r1)), + "e1d100b0 ldrh r0, [r1, #+0]"); + COMPARE(ldrh(r2, MemOperand(r3, 42)), + "e1d322ba ldrh r2, [r3, #+42]"); + COMPARE(ldrh(r4, MemOperand(r5, -42)), + "e15542ba ldrh r4, [r5, #-42]"); + COMPARE(ldrh(r6, MemOperand(r7, 42, PostIndex)), + "e0d762ba ldrh r6, [r7], #+42"); + COMPARE(ldrh(r8, MemOperand(r9, -42, PostIndex)), + "e05982ba ldrh r8, [r9], #-42"); + COMPARE(ldrh(r10, MemOperand(fp, 42, PreIndex)), + "e1fba2ba ldrh r10, [fp, #+42]!"); + COMPARE(ldrh(ip, MemOperand(sp, -42, PreIndex)), + "e17dc2ba ldrh ip, [sp, #-42]!"); + COMPARE(ldrh(r0, MemOperand(r1, r2)), + "e19100b2 ldrh r0, [r1, +r2]"); + COMPARE(ldrh(r0, MemOperand(r1, r2, NegOffset)), + "e11100b2 ldrh r0, [r1, -r2]"); + COMPARE(ldrh(r0, MemOperand(r1, r2, PostIndex)), + "e09100b2 ldrh r0, [r1], +r2"); + COMPARE(ldrh(r0, MemOperand(r1, r2, NegPostIndex)), + "e01100b2 ldrh r0, [r1], -r2"); + COMPARE(ldrh(r0, MemOperand(r1, r2, PreIndex)), + "e1b100b2 ldrh r0, [r1, +r2]!"); + COMPARE(ldrh(r0, MemOperand(r1, r2, NegPreIndex)), + "e13100b2 ldrh r0, [r1, -r2]!"); + + COMPARE(strh(r0, MemOperand(r1)), + "e1c100b0 strh r0, [r1, #+0]"); + COMPARE(strh(r2, MemOperand(r3, 42)), + "e1c322ba strh r2, [r3, #+42]"); + COMPARE(strh(r4, MemOperand(r5, -42)), + "e14542ba strh r4, [r5, #-42]"); + COMPARE(strh(r6, MemOperand(r7, 42, PostIndex)), + "e0c762ba strh r6, [r7], #+42"); + COMPARE(strh(r8, MemOperand(r9, -42, PostIndex)), + "e04982ba strh r8, [r9], #-42"); + COMPARE(strh(r10, MemOperand(fp, 42, PreIndex)), + "e1eba2ba strh r10, [fp, #+42]!"); + COMPARE(strh(ip, MemOperand(sp, -42, PreIndex)), + "e16dc2ba strh ip, [sp, #-42]!"); + COMPARE(strh(r0, MemOperand(r1, r2)), + "e18100b2 strh r0, [r1, +r2]"); + COMPARE(strh(r0, MemOperand(r1, r2, NegOffset)), + "e10100b2 strh r0, [r1, -r2]"); + COMPARE(strh(r0, MemOperand(r1, r2, PostIndex)), + "e08100b2 strh r0, [r1], +r2"); + COMPARE(strh(r0, MemOperand(r1, r2, NegPostIndex)), + "e00100b2 strh r0, [r1], -r2"); + COMPARE(strh(r0, MemOperand(r1, r2, PreIndex)), + "e1a100b2 strh r0, [r1, +r2]!"); + COMPARE(strh(r0, MemOperand(r1, r2, NegPreIndex)), + "e12100b2 strh r0, [r1, -r2]!"); + + COMPARE(ldr(r0, MemOperand(r1)), + "e5910000 ldr r0, [r1, #+0]"); + COMPARE(ldr(r2, MemOperand(r3, 42)), + "e593202a ldr r2, [r3, #+42]"); + COMPARE(ldr(r4, MemOperand(r5, -42)), + "e515402a ldr r4, [r5, #-42]"); + COMPARE(ldr(r6, MemOperand(r7, 42, PostIndex)), + "e497602a ldr r6, [r7], #+42"); + COMPARE(ldr(r8, MemOperand(r9, -42, PostIndex)), + "e419802a ldr r8, [r9], #-42"); + COMPARE(ldr(r10, MemOperand(fp, 42, PreIndex)), + "e5bba02a ldr r10, [fp, #+42]!"); + COMPARE(ldr(ip, MemOperand(sp, -42, PreIndex)), + "e53dc02a ldr ip, [sp, #-42]!"); + COMPARE(ldr(r0, MemOperand(r1, r2)), + "e7910002 ldr r0, [r1, +r2]"); + COMPARE(ldr(r0, MemOperand(r1, r2, NegOffset)), + "e7110002 ldr r0, [r1, -r2]"); + COMPARE(ldr(r0, MemOperand(r1, r2, PostIndex)), + "e6910002 ldr r0, [r1], +r2"); + COMPARE(ldr(r0, MemOperand(r1, r2, NegPostIndex)), + "e6110002 ldr r0, [r1], -r2"); + COMPARE(ldr(r0, MemOperand(r1, r2, PreIndex)), + "e7b10002 ldr r0, [r1, +r2]!"); + COMPARE(ldr(r0, MemOperand(r1, r2, NegPreIndex)), + "e7310002 ldr r0, [r1, -r2]!"); + + COMPARE(str(r0, MemOperand(r1)), + "e5810000 str r0, [r1, #+0]"); + COMPARE(str(r2, MemOperand(r3, 42)), + "e583202a str r2, [r3, #+42]"); + COMPARE(str(r4, MemOperand(r5, -42)), + "e505402a str r4, [r5, #-42]"); + COMPARE(str(r6, MemOperand(r7, 42, PostIndex)), + "e487602a str r6, [r7], #+42"); + COMPARE(str(r8, MemOperand(r9, -42, PostIndex)), + "e409802a str r8, [r9], #-42"); + COMPARE(str(r10, MemOperand(fp, 42, PreIndex)), + "e5aba02a str r10, [fp, #+42]!"); + COMPARE(str(ip, MemOperand(sp, -42, PreIndex)), + "e52dc02a str ip, [sp, #-42]!"); + COMPARE(str(r0, MemOperand(r1, r2)), + "e7810002 str r0, [r1, +r2]"); + COMPARE(str(r0, MemOperand(r1, r2, NegOffset)), + "e7010002 str r0, [r1, -r2]"); + COMPARE(str(r0, MemOperand(r1, r2, PostIndex)), + "e6810002 str r0, [r1], +r2"); + COMPARE(str(r0, MemOperand(r1, r2, NegPostIndex)), + "e6010002 str r0, [r1], -r2"); + COMPARE(str(r0, MemOperand(r1, r2, PreIndex)), + "e7a10002 str r0, [r1, +r2]!"); + COMPARE(str(r0, MemOperand(r1, r2, NegPreIndex)), + "e7210002 str r0, [r1, -r2]!"); + + if (CpuFeatures::IsSupported(ARMv7)) { + CpuFeatures::Scope scope(ARMv7); + COMPARE(ldrd(r0, r1, MemOperand(r1)), + "e1c100d0 ldrd r0, [r1, #+0]"); + COMPARE(ldrd(r2, r3, MemOperand(r3, 127)), + "e1c327df ldrd r2, [r3, #+127]"); + COMPARE(ldrd(r4, r5, MemOperand(r5, -127)), + "e14547df ldrd r4, [r5, #-127]"); + COMPARE(ldrd(r6, r7, MemOperand(r7, 127, PostIndex)), + "e0c767df ldrd r6, [r7], #+127"); + COMPARE(ldrd(r8, r9, MemOperand(r9, -127, PostIndex)), + "e04987df ldrd r8, [r9], #-127"); + COMPARE(ldrd(r10, fp, MemOperand(fp, 127, PreIndex)), + "e1eba7df ldrd r10, [fp, #+127]!"); + COMPARE(ldrd(ip, sp, MemOperand(sp, -127, PreIndex)), + "e16dc7df ldrd ip, [sp, #-127]!"); + + COMPARE(strd(r0, r1, MemOperand(r1)), + "e1c100f0 strd r0, [r1, #+0]"); + COMPARE(strd(r2, r3, MemOperand(r3, 127)), + "e1c327ff strd r2, [r3, #+127]"); + COMPARE(strd(r4, r5, MemOperand(r5, -127)), + "e14547ff strd r4, [r5, #-127]"); + COMPARE(strd(r6, r7, MemOperand(r7, 127, PostIndex)), + "e0c767ff strd r6, [r7], #+127"); + COMPARE(strd(r8, r9, MemOperand(r9, -127, PostIndex)), + "e04987ff strd r8, [r9], #-127"); + COMPARE(strd(r10, fp, MemOperand(fp, 127, PreIndex)), + "e1eba7ff strd r10, [fp, #+127]!"); + COMPARE(strd(ip, sp, MemOperand(sp, -127, PreIndex)), + "e16dc7ff strd ip, [sp, #-127]!"); + } + + VERIFY_RUN(); +} + diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc index c995aa8ed..9f7d0bb6e 100644 --- a/deps/v8/test/cctest/test-disasm-ia32.cc +++ b/deps/v8/test/cctest/test-disasm-ia32.cc @@ -58,7 +58,7 @@ TEST(DisasmIa320) { InitializeVM(); v8::HandleScope scope; v8::internal::byte buffer[2048]; - Assembler assm(buffer, sizeof buffer); + Assembler assm(Isolate::Current(), buffer, sizeof buffer); DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) // Short immediate instructions @@ -68,7 +68,7 @@ TEST(DisasmIa320) { __ sub(Operand(eax), Immediate(12345678)); __ xor_(eax, 12345678); __ and_(eax, 12345678); - Handle<FixedArray> foo = Factory::NewFixedArray(10, TENURED); + Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED); __ cmp(eax, foo); // ---- This one caused crash @@ -99,7 +99,7 @@ TEST(DisasmIa320) { __ cmp(edx, 3); __ cmp(edx, Operand(esp, 4)); __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000)); - Handle<FixedArray> foo2 = Factory::NewFixedArray(10, TENURED); + Handle<FixedArray> foo2 = FACTORY->NewFixedArray(10, TENURED); __ cmp(ebx, foo2); __ cmpb(ebx, Operand(ebp, ecx, times_2, 0)); __ cmpb(Operand(ebp, ecx, times_2, 0), ebx); @@ -272,7 +272,8 @@ TEST(DisasmIa320) { __ bind(&L2); __ call(Operand(ebx, ecx, times_4, 10000)); __ nop(); - Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); + Handle<Code> ic(Isolate::Current()->builtins()->builtin( + Builtins::kLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); __ nop(); __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY); @@ -282,7 +283,8 @@ TEST(DisasmIa320) { __ jmp(Operand(ebx, ecx, times_4, 10000)); #ifdef ENABLE_DEBUGGER_SUPPORT ExternalReference after_break_target = - ExternalReference(Debug_Address::AfterBreakTarget()); + ExternalReference(Debug_Address::AfterBreakTarget(), + assm.isolate()); __ jmp(Operand::StaticVariable(after_break_target)); #endif // ENABLE_DEBUGGER_SUPPORT __ jmp(ic, RelocInfo::CODE_TARGET); @@ -328,11 +330,6 @@ TEST(DisasmIa320) { __ j(less_equal, &Ljcc); __ j(greater, &Ljcc); - // checking hints - __ j(zero, &Ljcc, taken); - __ j(zero, &Ljcc, not_taken); - - // __ mov(Operand::StaticVariable(Top::handler_address()), eax); // 0xD9 instructions __ nop(); @@ -458,10 +455,10 @@ TEST(DisasmIa320) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef OBJECT_PRINT Code::cast(code)->Print(); diff --git a/deps/v8/test/cctest/test-disasm-mips.cc b/deps/v8/test/cctest/test-disasm-mips.cc new file mode 100644 index 000000000..901dbc1bf --- /dev/null +++ b/deps/v8/test/cctest/test-disasm-mips.cc @@ -0,0 +1,432 @@ +// 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() { + // Disable compilation of natives. + FLAG_disable_native_files = true; + if (env.IsEmpty()) { + env = v8::Context::New(); + } +} + + +bool DisassembleAndCompare(byte* pc, const char* compare_string) { + disasm::NameConverter converter; + disasm::Disassembler disasm(converter); + EmbeddedVector<char, 128> disasm_buffer; + + disasm.InstructionDecode(disasm_buffer, pc); + + if (strcmp(compare_string, disasm_buffer.start()) != 0) { + fprintf(stderr, + "expected: \n" + "%s\n" + "disassembled: \n" + "%s\n\n", + compare_string, disasm_buffer.start()); + return false; + } + return true; +} + + +// Setup 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() \ + InitializeVM(); \ + v8::HandleScope scope; \ + byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ + Assembler assm(Isolate::Current(), buffer, 4*1024); \ + bool failure = false; + + +// This macro assembles one instruction using the preallocated assembler and +// disassembles the generated instruction, comparing the output to the expected +// value. If the comparison fails an error message is printed, but the test +// continues to run until the end. +#define COMPARE(asm_, compare_string) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, compare_string)) failure = true; \ + } + + +// Verify that all invocations of the COMPARE macro passed successfully. +// Exit with a failure if at least one of the tests failed. +#define VERIFY_RUN() \ +if (failure) { \ + V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \ + } + + +TEST(Type0) { + SETUP(); + + COMPARE(addu(a0, a1, a2), + "00a62021 addu a0, a1, a2"); + COMPARE(addu(t2, t3, t4), + "016c5021 addu t2, t3, t4"); + COMPARE(addu(v0, v1, s0), + "00701021 addu v0, v1, s0"); + + COMPARE(subu(a0, a1, a2), + "00a62023 subu a0, a1, a2"); + COMPARE(subu(t2, t3, t4), + "016c5023 subu t2, t3, t4"); + COMPARE(subu(v0, v1, s0), + "00701023 subu v0, v1, s0"); + + COMPARE(mult(a0, a1), + "00850018 mult a0, a1"); + COMPARE(mult(t2, t3), + "014b0018 mult t2, t3"); + COMPARE(mult(v0, v1), + "00430018 mult v0, v1"); + + COMPARE(multu(a0, a1), + "00850019 multu a0, a1"); + COMPARE(multu(t2, t3), + "014b0019 multu t2, t3"); + COMPARE(multu(v0, v1), + "00430019 multu v0, v1"); + + COMPARE(div(a0, a1), + "0085001a div a0, a1"); + COMPARE(div(t2, t3), + "014b001a div t2, t3"); + COMPARE(div(v0, v1), + "0043001a div v0, v1"); + + COMPARE(divu(a0, a1), + "0085001b divu a0, a1"); + COMPARE(divu(t2, t3), + "014b001b divu t2, t3"); + 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"); + + COMPARE(addiu(a0, a1, 0x0), + "24a40000 addiu a0, a1, 0"); + COMPARE(addiu(s0, s1, 32767), + "26307fff addiu s0, s1, 32767"); + COMPARE(addiu(t2, t3, -32768), + "256a8000 addiu t2, t3, -32768"); + COMPARE(addiu(v0, v1, -1), + "2462ffff addiu v0, v1, -1"); + + COMPARE(and_(a0, a1, a2), + "00a62024 and a0, a1, a2"); + COMPARE(and_(s0, s1, s2), + "02328024 and s0, s1, s2"); + COMPARE(and_(t2, t3, t4), + "016c5024 and t2, t3, t4"); + COMPARE(and_(v0, v1, a2), + "00661024 and v0, v1, a2"); + + COMPARE(or_(a0, a1, a2), + "00a62025 or a0, a1, a2"); + COMPARE(or_(s0, s1, s2), + "02328025 or s0, s1, s2"); + COMPARE(or_(t2, t3, t4), + "016c5025 or t2, t3, t4"); + COMPARE(or_(v0, v1, a2), + "00661025 or v0, v1, a2"); + + COMPARE(xor_(a0, a1, a2), + "00a62026 xor a0, a1, a2"); + COMPARE(xor_(s0, s1, s2), + "02328026 xor s0, s1, s2"); + COMPARE(xor_(t2, t3, t4), + "016c5026 xor t2, t3, t4"); + COMPARE(xor_(v0, v1, a2), + "00661026 xor v0, v1, a2"); + + COMPARE(nor(a0, a1, a2), + "00a62027 nor a0, a1, a2"); + COMPARE(nor(s0, s1, s2), + "02328027 nor s0, s1, s2"); + COMPARE(nor(t2, t3, t4), + "016c5027 nor t2, t3, t4"); + COMPARE(nor(v0, v1, a2), + "00661027 nor v0, v1, a2"); + + COMPARE(andi(a0, a1, 0x1), + "30a40001 andi a0, a1, 0x1"); + COMPARE(andi(v0, v1, 0xffff), + "3062ffff andi v0, v1, 0xffff"); + + COMPARE(ori(a0, a1, 0x1), + "34a40001 ori a0, a1, 0x1"); + COMPARE(ori(v0, v1, 0xffff), + "3462ffff ori v0, v1, 0xffff"); + + COMPARE(xori(a0, a1, 0x1), + "38a40001 xori a0, a1, 0x1"); + COMPARE(xori(v0, v1, 0xffff), + "3862ffff xori v0, v1, 0xffff"); + + COMPARE(lui(a0, 0x1), + "3c040001 lui a0, 0x1"); + COMPARE(lui(v0, 0xffff), + "3c02ffff lui v0, 0xffff"); + + COMPARE(sll(a0, a1, 0), + "00052000 sll a0, a1, 0"); + COMPARE(sll(s0, s1, 8), + "00118200 sll s0, s1, 8"); + COMPARE(sll(t2, t3, 24), + "000b5600 sll t2, t3, 24"); + COMPARE(sll(v0, v1, 31), + "000317c0 sll v0, v1, 31"); + + COMPARE(sllv(a0, a1, a2), + "00c52004 sllv a0, a1, a2"); + COMPARE(sllv(s0, s1, s2), + "02518004 sllv s0, s1, s2"); + COMPARE(sllv(t2, t3, t4), + "018b5004 sllv t2, t3, t4"); + COMPARE(sllv(v0, v1, fp), + "03c31004 sllv v0, v1, fp"); + + COMPARE(srl(a0, a1, 0), + "00052002 srl a0, a1, 0"); + COMPARE(srl(s0, s1, 8), + "00118202 srl s0, s1, 8"); + COMPARE(srl(t2, t3, 24), + "000b5602 srl t2, t3, 24"); + COMPARE(srl(v0, v1, 31), + "000317c2 srl v0, v1, 31"); + + COMPARE(srlv(a0, a1, a2), + "00c52006 srlv a0, a1, a2"); + COMPARE(srlv(s0, s1, s2), + "02518006 srlv s0, s1, s2"); + COMPARE(srlv(t2, t3, t4), + "018b5006 srlv t2, t3, t4"); + COMPARE(srlv(v0, v1, fp), + "03c31006 srlv v0, v1, fp"); + + COMPARE(sra(a0, a1, 0), + "00052003 sra a0, a1, 0"); + COMPARE(sra(s0, s1, 8), + "00118203 sra s0, s1, 8"); + COMPARE(sra(t2, t3, 24), + "000b5603 sra t2, t3, 24"); + COMPARE(sra(v0, v1, 31), + "000317c3 sra v0, v1, 31"); + + COMPARE(srav(a0, a1, a2), + "00c52007 srav a0, a1, a2"); + COMPARE(srav(s0, s1, s2), + "02518007 srav s0, s1, s2"); + COMPARE(srav(t2, t3, t4), + "018b5007 srav t2, t3, t4"); + COMPARE(srav(v0, v1, fp), + "03c31007 srav v0, v1, fp"); + + COMPARE(rotr(a0, a1, 0), + "00252002 rotr a0, a1, 0"); + COMPARE(rotr(s0, s1, 8), + "00318202 rotr s0, s1, 8"); + COMPARE(rotr(t2, t3, 24), + "002b5602 rotr t2, t3, 24"); + COMPARE(rotr(v0, v1, 31), + "002317c2 rotr v0, v1, 31"); + + COMPARE(rotrv(a0, a1, a2), + "00c52046 rotrv a0, a1, a2"); + COMPARE(rotrv(s0, s1, s2), + "02518046 rotrv s0, s1, s2"); + COMPARE(rotrv(t2, t3, t4), + "018b5046 rotrv t2, t3, t4"); + COMPARE(rotrv(v0, v1, fp), + "03c31046 rotrv v0, v1, fp"); + + COMPARE(break_(0), + "0000000d break, code: 0x00000 (0)"); + COMPARE(break_(261120), + "00ff000d break, code: 0x3fc00 (261120)"); + COMPARE(break_(1047552), + "03ff000d break, code: 0xffc00 (1047552)"); + + COMPARE(tge(a0, a1, 0), + "00850030 tge a0, a1, code: 0x000"); + COMPARE(tge(s0, s1, 1023), + "0211fff0 tge s0, s1, code: 0x3ff"); + COMPARE(tgeu(a0, a1, 0), + "00850031 tgeu a0, a1, code: 0x000"); + COMPARE(tgeu(s0, s1, 1023), + "0211fff1 tgeu s0, s1, code: 0x3ff"); + COMPARE(tlt(a0, a1, 0), + "00850032 tlt a0, a1, code: 0x000"); + COMPARE(tlt(s0, s1, 1023), + "0211fff2 tlt s0, s1, code: 0x3ff"); + COMPARE(tltu(a0, a1, 0), + "00850033 tltu a0, a1, code: 0x000"); + COMPARE(tltu(s0, s1, 1023), + "0211fff3 tltu s0, s1, code: 0x3ff"); + COMPARE(teq(a0, a1, 0), + "00850034 teq a0, a1, code: 0x000"); + COMPARE(teq(s0, s1, 1023), + "0211fff4 teq s0, s1, code: 0x3ff"); + COMPARE(tne(a0, a1, 0), + "00850036 tne a0, a1, code: 0x000"); + COMPARE(tne(s0, s1, 1023), + "0211fff6 tne s0, s1, code: 0x3ff"); + + COMPARE(mfhi(a0), + "00002010 mfhi a0"); + COMPARE(mfhi(s2), + "00009010 mfhi s2"); + COMPARE(mfhi(t4), + "00006010 mfhi t4"); + COMPARE(mfhi(v1), + "00001810 mfhi v1"); + COMPARE(mflo(a0), + "00002012 mflo a0"); + COMPARE(mflo(s2), + "00009012 mflo s2"); + COMPARE(mflo(t4), + "00006012 mflo t4"); + COMPARE(mflo(v1), + "00001812 mflo v1"); + + COMPARE(slt(a0, a1, a2), + "00a6202a slt a0, a1, a2"); + COMPARE(slt(s0, s1, s2), + "0232802a slt s0, s1, s2"); + COMPARE(slt(t2, t3, t4), + "016c502a slt t2, t3, t4"); + COMPARE(slt(v0, v1, a2), + "0066102a slt v0, v1, a2"); + COMPARE(sltu(a0, a1, a2), + "00a6202b sltu a0, a1, a2"); + COMPARE(sltu(s0, s1, s2), + "0232802b sltu s0, s1, s2"); + COMPARE(sltu(t2, t3, t4), + "016c502b sltu t2, t3, t4"); + COMPARE(sltu(v0, v1, a2), + "0066102b sltu v0, v1, a2"); + + COMPARE(slti(a0, a1, 0), + "28a40000 slti a0, a1, 0"); + COMPARE(slti(s0, s1, 32767), + "2a307fff slti s0, s1, 32767"); + COMPARE(slti(t2, t3, -32768), + "296a8000 slti t2, t3, -32768"); + COMPARE(slti(v0, v1, -1), + "2862ffff slti v0, v1, -1"); + COMPARE(sltiu(a0, a1, 0), + "2ca40000 sltiu a0, a1, 0"); + COMPARE(sltiu(s0, s1, 32767), + "2e307fff sltiu s0, s1, 32767"); + COMPARE(sltiu(t2, t3, -32768), + "2d6a8000 sltiu t2, t3, -32768"); + 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"); + COMPARE(ins_(a0, a1, 31, 1), + "7ca4ffc4 ins a0, a1, 31, 1"); + COMPARE(ins_(s6, s7, 30, 2), + "7ef6ff84 ins s6, s7, 30, 2"); + COMPARE(ins_(v0, v1, 0, 32), + "7c62f804 ins v0, v1, 0, 32"); + COMPARE(ext_(a0, a1, 31, 1), + "7ca407c0 ext a0, a1, 31, 1"); + COMPARE(ext_(s6, s7, 30, 2), + "7ef60f80 ext s6, s7, 30, 2"); + COMPARE(ext_(v0, v1, 0, 32), + "7c62f800 ext v0, v1, 0, 32"); + + VERIFY_RUN(); +} diff --git a/deps/v8/test/cctest/test-func-name-inference.cc b/deps/v8/test/cctest/test-func-name-inference.cc index 563cc4bf4..4d993af4a 100644 --- a/deps/v8/test/cctest/test-func-name-inference.cc +++ b/deps/v8/test/cctest/test-func-name-inference.cc @@ -1,4 +1,4 @@ -// Copyright 2007-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: @@ -36,6 +36,7 @@ using ::v8::internal::CStrVector; using ::v8::internal::Factory; using ::v8::internal::Handle; using ::v8::internal::Heap; +using ::v8::internal::Isolate; using ::v8::internal::JSFunction; using ::v8::internal::Object; using ::v8::internal::Runtime; @@ -77,15 +78,20 @@ static void CheckFunctionName(v8::Handle<v8::Script> script, // Find the position of a given func source substring in the source. Handle<String> func_pos_str = - Factory::NewStringFromAscii(CStrVector(func_pos_src)); - int func_pos = Runtime::StringMatch(script_src, func_pos_str, 0); + FACTORY->NewStringFromAscii(CStrVector(func_pos_src)); + int func_pos = Runtime::StringMatch(Isolate::Current(), + script_src, + func_pos_str, + 0); CHECK_NE(0, func_pos); #ifdef ENABLE_DEBUGGER_SUPPORT // Obtain SharedFunctionInfo for the function. Object* shared_func_info_ptr = - Runtime::FindSharedFunctionInfoInScript(i_script, func_pos); - CHECK(shared_func_info_ptr != Heap::undefined_value()); + Runtime::FindSharedFunctionInfoInScript(Isolate::Current(), + i_script, + func_pos); + CHECK(shared_func_info_ptr != HEAP->undefined_value()); Handle<SharedFunctionInfo> shared_func_info( SharedFunctionInfo::cast(shared_func_info_ptr)); @@ -275,3 +281,83 @@ TEST(Issue380) { "}"); CheckFunctionName(script, "return p", ""); } + + +TEST(MultipleAssignments) { + InitializeVM(); + v8::HandleScope scope; + + v8::Handle<v8::Script> script = Compile( + "var fun1 = fun2 = function () { return 1; }\n" + "var bar1 = bar2 = bar3 = function () { return 2; }\n" + "foo1 = foo2 = function () { return 3; }\n" + "baz1 = baz2 = baz3 = function () { return 4; }"); + CheckFunctionName(script, "return 1", "fun2"); + CheckFunctionName(script, "return 2", "bar3"); + CheckFunctionName(script, "return 3", "foo2"); + CheckFunctionName(script, "return 4", "baz3"); +} + + +TEST(AsConstructorParameter) { + InitializeVM(); + v8::HandleScope scope; + + v8::Handle<v8::Script> script = Compile( + "function Foo() {}\n" + "var foo = new Foo(function() { return 1; })\n" + "var bar = new Foo(function() { return 2; }, function() { return 3; })"); + CheckFunctionName(script, "return 1", ""); + CheckFunctionName(script, "return 2", ""); + CheckFunctionName(script, "return 3", ""); +} + + +TEST(FactoryHashmap) { + InitializeVM(); + v8::HandleScope scope; + + v8::Handle<v8::Script> script = Compile( + "function createMyObj() {\n" + " var obj = {};\n" + " obj[\"method1\"] = function() { return 1; }\n" + " obj[\"method2\"] = function() { return 2; }\n" + " return obj;\n" + "}"); + CheckFunctionName(script, "return 1", "obj.method1"); + CheckFunctionName(script, "return 2", "obj.method2"); +} + + +TEST(FactoryHashmapVariable) { + InitializeVM(); + v8::HandleScope scope; + + v8::Handle<v8::Script> script = Compile( + "function createMyObj() {\n" + " var obj = {};\n" + " var methodName = \"method1\";\n" + " obj[methodName] = function() { return 1; }\n" + " methodName = \"method2\";\n" + " obj[methodName] = function() { return 2; }\n" + " return obj;\n" + "}"); + // Can't infer function names statically. + CheckFunctionName(script, "return 1", "obj.(anonymous function)"); + CheckFunctionName(script, "return 2", "obj.(anonymous function)"); +} + + +TEST(FactoryHashmapConditional) { + InitializeVM(); + v8::HandleScope scope; + + v8::Handle<v8::Script> script = Compile( + "function createMyObj() {\n" + " var obj = {};\n" + " obj[0 ? \"method1\" : \"method2\"] = function() { return 1; }\n" + " return obj;\n" + "}"); + // Can't infer the function name statically. + CheckFunctionName(script, "return 1", "obj.(anonymous function)"); +} diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index ad242fe79..a2426cc0f 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -1,387 +1,18 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // // Tests for heap profiler #ifdef ENABLE_LOGGING_AND_PROFILING #include "v8.h" + +#include "cctest.h" #include "heap-profiler.h" #include "snapshot.h" -#include "string-stream.h" -#include "cctest.h" -#include "zone-inl.h" +#include "utils-inl.h" #include "../include/v8-profiler.h" namespace i = v8::internal; -using i::ClustersCoarser; -using i::JSObjectsCluster; -using i::JSObjectsRetainerTree; -using i::JSObjectsClusterTree; -using i::RetainerHeapProfile; - - -namespace { - -class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { - public: - ConstructorHeapProfileTestHelper() - : i::ConstructorHeapProfile(), - f_name_(i::Factory::NewStringFromAscii(i::CStrVector("F"))), - f_count_(0) { - } - - void Call(const JSObjectsCluster& cluster, - const i::NumberAndSizeInfo& number_and_size) { - if (f_name_->Equals(cluster.constructor())) { - CHECK_EQ(f_count_, 0); - f_count_ = number_and_size.number(); - CHECK_GT(f_count_, 0); - } - } - - int f_count() { return f_count_; } - - private: - i::Handle<i::String> f_name_; - int f_count_; -}; - -} // namespace - - -TEST(ConstructorProfile) { - v8::HandleScope scope; - LocalContext env; - - CompileRun( - "function F() {} // A constructor\n" - "var f1 = new F();\n" - "var f2 = new F();\n"); - - ConstructorHeapProfileTestHelper cons_profile; - i::AssertNoAllocation no_alloc; - i::HeapIterator iterator; - for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) - cons_profile.CollectStats(obj); - CHECK_EQ(0, cons_profile.f_count()); - cons_profile.PrintStats(); - CHECK_EQ(2, cons_profile.f_count()); -} - - -static JSObjectsCluster AddHeapObjectToTree(JSObjectsRetainerTree* tree, - i::String* constructor, - int instance, - JSObjectsCluster* ref1 = NULL, - JSObjectsCluster* ref2 = NULL, - JSObjectsCluster* ref3 = NULL) { - JSObjectsCluster o(constructor, reinterpret_cast<i::Object*>(instance)); - JSObjectsClusterTree* o_tree = new JSObjectsClusterTree(); - JSObjectsClusterTree::Locator o_loc; - if (ref1 != NULL) o_tree->Insert(*ref1, &o_loc); - if (ref2 != NULL) o_tree->Insert(*ref2, &o_loc); - if (ref3 != NULL) o_tree->Insert(*ref3, &o_loc); - JSObjectsRetainerTree::Locator loc; - tree->Insert(o, &loc); - loc.set_value(o_tree); - return o; -} - - -static void AddSelfReferenceToTree(JSObjectsRetainerTree* tree, - JSObjectsCluster* self_ref) { - JSObjectsRetainerTree::Locator loc; - CHECK(tree->Find(*self_ref, &loc)); - JSObjectsClusterTree::Locator o_loc; - CHECK_NE(NULL, loc.value()); - loc.value()->Insert(*self_ref, &o_loc); -} - - -static inline void CheckEqualsHelper(const char* file, int line, - const char* expected_source, - const JSObjectsCluster& expected, - const char* value_source, - const JSObjectsCluster& value) { - if (JSObjectsCluster::Compare(expected, value) != 0) { - i::HeapStringAllocator allocator; - i::StringStream stream(&allocator); - stream.Add("# Expected: "); - expected.DebugPrint(&stream); - stream.Add("\n# Found: "); - value.DebugPrint(&stream); - V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n%s", - expected_source, value_source, - *stream.ToCString()); - } -} - - -static inline void CheckNonEqualsHelper(const char* file, int line, - const char* expected_source, - const JSObjectsCluster& expected, - const char* value_source, - const JSObjectsCluster& value) { - if (JSObjectsCluster::Compare(expected, value) == 0) { - i::HeapStringAllocator allocator; - i::StringStream stream(&allocator); - stream.Add("# !Expected: "); - expected.DebugPrint(&stream); - stream.Add("\n# Found: "); - value.DebugPrint(&stream); - V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n%s", - expected_source, value_source, - *stream.ToCString()); - } -} - - -TEST(ClustersCoarserSimple) { - v8::HandleScope scope; - LocalContext env; - - i::ZoneScope zn_scope(i::DELETE_ON_EXIT); - - JSObjectsRetainerTree tree; - JSObjectsCluster function(i::Heap::function_class_symbol()); - JSObjectsCluster a(*i::Factory::NewStringFromAscii(i::CStrVector("A"))); - JSObjectsCluster b(*i::Factory::NewStringFromAscii(i::CStrVector("B"))); - - // o1 <- Function - JSObjectsCluster o1 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); - // o2 <- Function - JSObjectsCluster o2 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); - // o3 <- A, B - JSObjectsCluster o3 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &a, &b); - // o4 <- B, A - JSObjectsCluster o4 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x400, &b, &a); - // o5 <- A, B, Function - JSObjectsCluster o5 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x500, - &a, &b, &function); - - ClustersCoarser coarser; - coarser.Process(&tree); - - CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); - CHECK_EQ(coarser.GetCoarseEquivalent(o3), coarser.GetCoarseEquivalent(o4)); - CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o3)); - CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o5)); -} - - -TEST(ClustersCoarserMultipleConstructors) { - v8::HandleScope scope; - LocalContext env; - - i::ZoneScope zn_scope(i::DELETE_ON_EXIT); - - JSObjectsRetainerTree tree; - JSObjectsCluster function(i::Heap::function_class_symbol()); - - // o1 <- Function - JSObjectsCluster o1 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); - // a1 <- Function - JSObjectsCluster a1 = - AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x1000, &function); - // o2 <- Function - JSObjectsCluster o2 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); - // a2 <- Function - JSObjectsCluster a2 = - AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x2000, &function); - - ClustersCoarser coarser; - coarser.Process(&tree); - - CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); - CHECK_EQ(coarser.GetCoarseEquivalent(a1), coarser.GetCoarseEquivalent(a2)); -} - - -TEST(ClustersCoarserPathsTraversal) { - v8::HandleScope scope; - LocalContext env; - - i::ZoneScope zn_scope(i::DELETE_ON_EXIT); - - JSObjectsRetainerTree tree; - - // On the following graph: - // - // p - // <- o21 <- o11 <- - // q o - // <- o22 <- o12 <- - // r - // - // we expect that coarser will deduce equivalences: p ~ q ~ r, - // o21 ~ o22, and o11 ~ o12. - - JSObjectsCluster o = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); - JSObjectsCluster o11 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); - JSObjectsCluster o12 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); - JSObjectsCluster o21 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x210, &o11); - JSObjectsCluster o22 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x220, &o12); - JSObjectsCluster p = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o21); - JSObjectsCluster q = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o21, &o22); - JSObjectsCluster r = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o22); - - ClustersCoarser coarser; - coarser.Process(&tree); - - CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); - CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o11)); - CHECK_EQ(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o12)); - CHECK_EQ(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(o22)); - CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o21)); - CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); - CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); - CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); - CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(p)); - CHECK_NE(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(p)); -} - - -TEST(ClustersCoarserSelf) { - v8::HandleScope scope; - LocalContext env; - - i::ZoneScope zn_scope(i::DELETE_ON_EXIT); - - JSObjectsRetainerTree tree; - - // On the following graph: - // - // p (self-referencing) - // <- o1 <- - // q (self-referencing) o - // <- o2 <- - // r (self-referencing) - // - // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2; - - JSObjectsCluster o = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); - JSObjectsCluster o1 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); - JSObjectsCluster o2 = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); - JSObjectsCluster p = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o1); - AddSelfReferenceToTree(&tree, &p); - JSObjectsCluster q = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o1, &o2); - AddSelfReferenceToTree(&tree, &q); - JSObjectsCluster r = - AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o2); - AddSelfReferenceToTree(&tree, &r); - - ClustersCoarser coarser; - coarser.Process(&tree); - - CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); - CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o1)); - CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); - CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); - CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); - CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); - CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(p)); -} - - -namespace { - -class RetainerProfilePrinter : public RetainerHeapProfile::Printer { - public: - RetainerProfilePrinter() : stream_(&allocator_), lines_(100) {} - - void PrintRetainers(const JSObjectsCluster& cluster, - const i::StringStream& retainers) { - cluster.Print(&stream_); - stream_.Add("%s", *(retainers.ToCString())); - stream_.Put('\0'); - } - - const char* GetRetainers(const char* constructor) { - FillLines(); - const size_t cons_len = strlen(constructor); - for (int i = 0; i < lines_.length(); ++i) { - if (strncmp(constructor, lines_[i], cons_len) == 0 && - lines_[i][cons_len] == ',') { - return lines_[i] + cons_len + 1; - } - } - return NULL; - } - - private: - void FillLines() { - if (lines_.length() > 0) return; - stream_.Put('\0'); - stream_str_ = stream_.ToCString(); - const char* pos = *stream_str_; - while (pos != NULL && *pos != '\0') { - lines_.Add(pos); - pos = strchr(pos, '\0'); - if (pos != NULL) ++pos; - } - } - - i::HeapStringAllocator allocator_; - i::StringStream stream_; - i::SmartPointer<const char> stream_str_; - i::List<const char*> lines_; -}; - -} // namespace - - -TEST(RetainerProfile) { - v8::HandleScope scope; - LocalContext env; - - CompileRun( - "function A() {}\n" - "function B(x) { this.x = x; }\n" - "function C(x) { this.x1 = x; this.x2 = x; }\n" - "var a = new A();\n" - "var b1 = new B(a), b2 = new B(a);\n" - "var c = new C(a);"); - - RetainerHeapProfile ret_profile; - i::AssertNoAllocation no_alloc; - i::HeapIterator iterator; - for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) - ret_profile.CollectStats(obj); - ret_profile.CoarseAndAggregate(); - RetainerProfilePrinter printer; - ret_profile.DebugPrintStats(&printer); - const char* retainers_of_a = printer.GetRetainers("A"); - // The order of retainers is unspecified, so we check string length, and - // verify each retainer separately. - CHECK_EQ(i::StrLength("(global property);1,B;2,C;2"), - i::StrLength(retainers_of_a)); - CHECK(strstr(retainers_of_a, "(global property);1") != NULL); - CHECK(strstr(retainers_of_a, "B;2") != NULL); - CHECK(strstr(retainers_of_a, "C;2") != NULL); - CHECK_EQ("(global property);2", printer.GetRetainers("B")); - CHECK_EQ("(global property);1", printer.GetRetainers("C")); -} - namespace { @@ -414,8 +45,8 @@ static const v8::HeapGraphNode* GetGlobalObject( CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount()); const v8::HeapGraphNode* global_obj = snapshot->GetRoot()->GetChild(0)->GetToNode(); - CHECK_EQ("Object", const_cast<i::HeapEntry*>( - reinterpret_cast<const i::HeapEntry*>(global_obj))->name()); + CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6)); return global_obj; } @@ -433,19 +64,6 @@ static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, } -static bool IsNodeRetainedAs(const v8::HeapGraphNode* node, - v8::HeapGraphEdge::Type type, - const char* name) { - for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = node->GetRetainer(i); - v8::String::AsciiValue prop_name(prop->GetName()); - if (prop->GetType() == type && strcmp(name, *prop_name) == 0) - return true; - } - return false; -} - - static bool HasString(const v8::HeapGraphNode* node, const char* contents) { for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { const v8::HeapGraphEdge* prop = node->GetChild(i); @@ -496,56 +114,6 @@ TEST(HeapSnapshot) { CHECK(det.has_A2); CHECK(det.has_B2); CHECK(det.has_C2); - - /* - // Currently disabled. Too many retaining paths emerge, need to - // reduce the amount. - - // Verify 'a2' object retainers. They are: - // - (global object).a2 - // - c2.x1, c2.x2, c2[1] - // - b2_1 and b2_2 closures: via 'x' variable - CHECK_EQ(6, a2_node->GetRetainingPathsCount()); - bool has_global_obj_a2_ref = false; - bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false; - bool has_b2_1_x_ref = false, has_b2_2_x_ref = false; - for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) { - const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i); - const int edges_count = path->GetEdgesCount(); - CHECK_GT(edges_count, 0); - const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1); - v8::String::AsciiValue last_edge_name(last_edge->GetName()); - if (strcmp("a2", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kProperty) { - has_global_obj_a2_ref = true; - continue; - } - CHECK_GT(edges_count, 1); - const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2); - v8::String::AsciiValue prev_edge_name(prev_edge->GetName()); - if (strcmp("x1", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kProperty - && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true; - if (strcmp("x2", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kProperty - && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true; - if (strcmp("1", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kElement - && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true; - if (strcmp("x", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable - && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true; - if (strcmp("x", *last_edge_name) == 0 - && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable - && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true; - } - CHECK(has_global_obj_a2_ref); - CHECK(has_c2_x1_ref); - CHECK(has_c2_x2_ref); - CHECK(has_c2_1_ref); - CHECK(has_b2_1_x_ref); - CHECK(has_b2_2_x_ref); - */ } @@ -637,10 +205,10 @@ TEST(HeapSnapshotCodeObjects) { // Find references to code. const v8::HeapGraphNode* compiled_code = - GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code"); + GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared"); CHECK_NE(NULL, compiled_code); const v8::HeapGraphNode* lazy_code = - GetProperty(lazy, v8::HeapGraphEdge::kInternal, "code"); + GetProperty(lazy, v8::HeapGraphEdge::kInternal, "shared"); CHECK_NE(NULL, lazy_code); // Verify that non-compiled code doesn't contain references to "x" @@ -730,7 +298,7 @@ TEST(HeapEntryIdsAndGC) { const v8::HeapSnapshot* snapshot1 = v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); - i::Heap::CollectAllGarbage(true); // Enforce compaction. + HEAP->CollectAllGarbage(true); // Enforce compaction. const v8::HeapSnapshot* snapshot2 = v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); @@ -774,76 +342,6 @@ TEST(HeapEntryIdsAndGC) { } -TEST(HeapSnapshotsDiff) { - v8::HandleScope scope; - LocalContext env; - - CompileRun( - "function A() {}\n" - "function B(x) { this.x = x; }\n" - "function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n" - "var a = new A();\n" - "var b = new B(a);"); - const v8::HeapSnapshot* snapshot1 = - v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); - - CompileRun( - "delete a;\n" - "b.x = null;\n" - "var a = new A2(20);\n" - "var b2 = new B(a);"); - const v8::HeapSnapshot* snapshot2 = - v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); - - const v8::HeapSnapshotsDiff* diff = snapshot1->CompareWith(snapshot2); - - // Verify additions: ensure that addition of A and B was detected. - const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot(); - bool found_A = false, found_B = false; - uint64_t s1_A_id = 0; - for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = additions_root->GetChild(i); - const v8::HeapGraphNode* node = prop->GetToNode(); - if (node->GetType() == v8::HeapGraphNode::kObject) { - v8::String::AsciiValue node_name(node->GetName()); - if (strcmp(*node_name, "A2") == 0) { - CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a")); - CHECK(!found_A); - found_A = true; - s1_A_id = node->GetId(); - } else if (strcmp(*node_name, "B") == 0) { - CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2")); - CHECK(!found_B); - found_B = true; - } - } - } - CHECK(found_A); - CHECK(found_B); - - // Verify deletions: ensure that deletion of A was detected. - const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot(); - bool found_A_del = false; - uint64_t s2_A_id = 0; - for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = deletions_root->GetChild(i); - const v8::HeapGraphNode* node = prop->GetToNode(); - if (node->GetType() == v8::HeapGraphNode::kObject) { - v8::String::AsciiValue node_name(node->GetName()); - if (strcmp(*node_name, "A") == 0) { - CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a")); - CHECK(!found_A_del); - found_A_del = true; - s2_A_id = node->GetId(); - } - } - } - CHECK(found_A_del); - CHECK_NE_UINT64_T(0, s1_A_id); - CHECK(s1_A_id != s2_A_id); -} - - TEST(HeapSnapshotRootPreservedAfterSorting) { v8::HandleScope scope; LocalContext env; @@ -857,116 +355,6 @@ TEST(HeapSnapshotRootPreservedAfterSorting) { } -static const v8::HeapGraphNode* GetChild( - const v8::HeapGraphNode* node, - v8::HeapGraphNode::Type type, - const char* name, - const v8::HeapGraphNode* after = NULL) { - bool ignore_child = after == NULL ? false : true; - for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = node->GetChild(i); - const v8::HeapGraphNode* child = prop->GetToNode(); - v8::String::AsciiValue child_name(child->GetName()); - if (!ignore_child - && child->GetType() == type - && strcmp(name, *child_name) == 0) - return child; - if (after != NULL && child == after) ignore_child = false; - } - return NULL; -} - -static bool IsNodeRetainedAs(const v8::HeapGraphNode* node, - int element) { - for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = node->GetRetainer(i); - if (prop->GetType() == v8::HeapGraphEdge::kElement - && element == prop->GetName()->Int32Value()) - return true; - } - return false; -} - -TEST(AggregatedHeapSnapshot) { - v8::HandleScope scope; - LocalContext env; - - CompileRun( - "function A() {}\n" - "function B(x) { this.x = x; }\n" - "var a = new A();\n" - "var b = new B(a);"); - const v8::HeapSnapshot* snapshot = - v8::HeapProfiler::TakeSnapshot( - v8::String::New("agg"), v8::HeapSnapshot::kAggregated); - const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(), - v8::HeapGraphNode::kHidden, - "STRING_TYPE"); - CHECK_NE(NULL, strings); - CHECK_NE(0, strings->GetSelfSize()); - CHECK_NE(0, strings->GetInstancesCount()); - const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(), - v8::HeapGraphNode::kHidden, - "MAP_TYPE"); - CHECK_NE(NULL, maps); - CHECK_NE(0, maps->GetSelfSize()); - CHECK_NE(0, maps->GetInstancesCount()); - - const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(), - v8::HeapGraphNode::kObject, - "A"); - CHECK_NE(NULL, a); - CHECK_NE(0, a->GetSelfSize()); - CHECK_EQ(1, a->GetInstancesCount()); - - const v8::HeapGraphNode* b = GetChild(snapshot->GetRoot(), - v8::HeapGraphNode::kObject, - "B"); - CHECK_NE(NULL, b); - CHECK_NE(0, b->GetSelfSize()); - CHECK_EQ(1, b->GetInstancesCount()); - - const v8::HeapGraphNode* glob_prop = GetChild(snapshot->GetRoot(), - v8::HeapGraphNode::kObject, - "(global property)", - b); - CHECK_NE(NULL, glob_prop); - CHECK_EQ(0, glob_prop->GetSelfSize()); - CHECK_EQ(0, glob_prop->GetInstancesCount()); - CHECK_NE(0, glob_prop->GetChildrenCount()); - - const v8::HeapGraphNode* a_from_glob_prop = GetChild( - glob_prop, - v8::HeapGraphNode::kObject, - "A"); - CHECK_NE(NULL, a_from_glob_prop); - CHECK_EQ(0, a_from_glob_prop->GetSelfSize()); - CHECK_EQ(0, a_from_glob_prop->GetInstancesCount()); - CHECK_EQ(0, a_from_glob_prop->GetChildrenCount()); // Retains nothing. - CHECK(IsNodeRetainedAs(a_from_glob_prop, 1)); // (global propery) has 1 ref. - - const v8::HeapGraphNode* b_with_children = GetChild( - snapshot->GetRoot(), - v8::HeapGraphNode::kObject, - "B", - b); - CHECK_NE(NULL, b_with_children); - CHECK_EQ(0, b_with_children->GetSelfSize()); - CHECK_EQ(0, b_with_children->GetInstancesCount()); - CHECK_NE(0, b_with_children->GetChildrenCount()); - - const v8::HeapGraphNode* a_from_b = GetChild( - b_with_children, - v8::HeapGraphNode::kObject, - "A"); - CHECK_NE(NULL, a_from_b); - CHECK_EQ(0, a_from_b->GetSelfSize()); - CHECK_EQ(0, a_from_b->GetInstancesCount()); - CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing. - CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A. -} - - TEST(HeapEntryDominator) { // The graph looks like this: // @@ -1179,21 +567,6 @@ TEST(HeapSnapshotJSONSerializationAborting) { } -// Must not crash in debug mode. -TEST(AggregatedHeapSnapshotJSONSerialization) { - v8::HandleScope scope; - LocalContext env; - - const v8::HeapSnapshot* snapshot = - v8::HeapProfiler::TakeSnapshot( - v8::String::New("agg"), v8::HeapSnapshot::kAggregated); - TestJSONStream stream; - snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); - CHECK_GT(stream.size(), 0); - CHECK_EQ(1, stream.eos_signaled()); -} - - TEST(HeapSnapshotGetNodeById) { v8::HandleScope scope; LocalContext env; @@ -1258,4 +631,267 @@ TEST(TakeHeapSnapshotAborting) { CHECK_GT(control.total(), 0); } + +namespace { + +class TestRetainedObjectInfo : public v8::RetainedObjectInfo { + public: + TestRetainedObjectInfo(int hash, + const char* label, + intptr_t element_count = -1, + intptr_t size = -1) + : disposed_(false), + hash_(hash), + label_(label), + element_count_(element_count), + size_(size) { + instances.Add(this); + } + virtual ~TestRetainedObjectInfo() {} + virtual void Dispose() { + CHECK(!disposed_); + disposed_ = true; + } + virtual bool IsEquivalent(RetainedObjectInfo* other) { + return GetHash() == other->GetHash(); + } + virtual intptr_t GetHash() { return hash_; } + virtual const char* GetLabel() { return label_; } + virtual intptr_t GetElementCount() { return element_count_; } + virtual intptr_t GetSizeInBytes() { return size_; } + bool disposed() { return disposed_; } + + static v8::RetainedObjectInfo* WrapperInfoCallback( + uint16_t class_id, v8::Handle<v8::Value> wrapper) { + if (class_id == 1) { + if (wrapper->IsString()) { + v8::String::AsciiValue ascii(wrapper); + if (strcmp(*ascii, "AAA") == 0) + return new TestRetainedObjectInfo(1, "aaa", 100); + else if (strcmp(*ascii, "BBB") == 0) + return new TestRetainedObjectInfo(1, "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"); + } + } + CHECK(false); + return NULL; + } + + static i::List<TestRetainedObjectInfo*> instances; + + private: + bool disposed_; + int category_; + int hash_; + const char* label_; + intptr_t element_count_; + intptr_t size_; +}; + + +i::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances; +} + + +static const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent, + v8::HeapGraphNode::Type type, + const char* name) { + for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) { + const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode(); + if (node->GetType() == type && strcmp(name, + const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) { + return node; + } + } + return NULL; +} + + +TEST(HeapSnapshotRetainedObjectInfo) { + v8::HandleScope scope; + LocalContext env; + + v8::HeapProfiler::DefineWrapperClass( + 1, TestRetainedObjectInfo::WrapperInfoCallback); + v8::HeapProfiler::DefineWrapperClass( + 2, TestRetainedObjectInfo::WrapperInfoCallback); + v8::Persistent<v8::String> p_AAA = + v8::Persistent<v8::String>::New(v8_str("AAA")); + p_AAA.SetWrapperClassId(1); + v8::Persistent<v8::String> p_BBB = + v8::Persistent<v8::String>::New(v8_str("BBB")); + p_BBB.SetWrapperClassId(1); + v8::Persistent<v8::String> p_CCC = + v8::Persistent<v8::String>::New(v8_str("CCC")); + p_CCC.SetWrapperClassId(2); + CHECK_EQ(0, TestRetainedObjectInfo::instances.length()); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("retained")); + + CHECK_EQ(3, TestRetainedObjectInfo::instances.length()); + for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) { + CHECK(TestRetainedObjectInfo::instances[i]->disposed()); + 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* aaa = GetNode( + natives, v8::HeapGraphNode::kNative, "aaa / 100 entries"); + CHECK_NE(NULL, aaa); + const v8::HeapGraphNode* ccc = GetNode( + natives, 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); + const v8::HeapGraphNode* n_BBB = GetNode( + aaa, v8::HeapGraphNode::kString, "BBB"); + CHECK_NE(NULL, n_BBB); + CHECK_EQ(1, ccc->GetChildrenCount()); + const v8::HeapGraphNode* n_CCC = GetNode( + ccc, v8::HeapGraphNode::kString, "CCC"); + CHECK_NE(NULL, n_CCC); + + CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "native")); + CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "native")); + CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native")); +} + + +TEST(DeleteAllHeapSnapshots) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("2"))); + CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); +} + + +TEST(DeleteHeapSnapshot) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + const v8::HeapSnapshot* s1 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("1")); + CHECK_NE(NULL, s1); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid1 = s1->GetUid(); + CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1)); + const_cast<v8::HeapSnapshot*>(s1)->Delete(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1)); + + const v8::HeapSnapshot* s2 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("2")); + CHECK_NE(NULL, s2); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid2 = s2->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); + CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2)); + const v8::HeapSnapshot* s3 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("3")); + CHECK_NE(NULL, s3); + CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid3 = s3->GetUid(); + CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); + CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); + const_cast<v8::HeapSnapshot*>(s2)->Delete(); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2)); + CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); + const_cast<v8::HeapSnapshot*>(s3)->Delete(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3)); +} + + +TEST(DocumentURL) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("document = { URL:\"abcdefgh\" };"); + + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("document")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + CHECK_EQ("Object / abcdefgh", + const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(global))->name()); +} + + +TEST(DocumentWithException) { + v8::HandleScope scope; + LocalContext env; + + CompileRun( + "this.__defineGetter__(\"document\", function() { throw new Error(); })"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("document")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + CHECK_EQ("Object", + const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(global))->name()); +} + + +TEST(DocumentURLWithException) { + v8::HandleScope scope; + LocalContext env; + + CompileRun( + "function URLWithException() {}\n" + "URLWithException.prototype = { get URL() { throw new Error(); } };\n" + "document = { URL: new URLWithException() };"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("document")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + CHECK_EQ("Object", + const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(global))->name()); +} + + +TEST(NodesIteration) { + v8::HandleScope scope; + LocalContext env; + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("iteration")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + // Verify that we can find this object by iteration. + const int nodes_count = snapshot->GetNodesCount(); + int count = 0; + for (int i = 0; i < nodes_count; ++i) { + if (snapshot->GetNode(i) == global) + ++count; + } + CHECK_EQ(1, count); +} + #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 9cce01eae..fac9f0a1b 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -24,9 +24,9 @@ static void InitializeVM() { static void CheckMap(Map* map, int type, int instance_size) { CHECK(map->IsHeapObject()); #ifdef DEBUG - CHECK(Heap::Contains(map)); + CHECK(HEAP->Contains(map)); #endif - CHECK_EQ(Heap::meta_map(), map->map()); + CHECK_EQ(HEAP->meta_map(), map->map()); CHECK_EQ(type, map->instance_type()); CHECK_EQ(instance_size, map->instance_size()); } @@ -34,10 +34,10 @@ static void CheckMap(Map* map, int type, int instance_size) { TEST(HeapMaps) { InitializeVM(); - CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize); - CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize); - CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel); - CheckMap(Heap::string_map(), STRING_TYPE, kVariableSizeSentinel); + CheckMap(HEAP->meta_map(), MAP_TYPE, Map::kSize); + CheckMap(HEAP->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize); + CheckMap(HEAP->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel); + CheckMap(HEAP->string_map(), STRING_TYPE, kVariableSizeSentinel); } @@ -58,7 +58,7 @@ static void CheckSmi(int value, const char* string) { static void CheckNumber(double value, const char* string) { - Object* obj = Heap::NumberFromDouble(value)->ToObjectChecked(); + Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked(); CHECK(obj->IsNumber()); bool exc; Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc); @@ -70,33 +70,33 @@ static void CheckFindCodeObject() { // Test FindCodeObject #define __ assm. - Assembler assm(NULL, 0); + Assembler assm(Isolate::Current(), NULL, 0); __ nop(); // supported on all architectures CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode( + Object* code = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); HeapObject* obj = HeapObject::cast(code); Address obj_addr = obj->address(); for (int i = 0; i < obj->Size(); i += kPointerSize) { - Object* found = Heap::FindCodeObject(obj_addr + i); + Object* found = HEAP->FindCodeObject(obj_addr + i); CHECK_EQ(code, found); } - Object* copy = Heap::CreateCode( + Object* copy = HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); CHECK(copy->IsCode()); HeapObject* obj_copy = HeapObject::cast(copy); - Object* not_right = Heap::FindCodeObject(obj_copy->address() + + Object* not_right = HEAP->FindCodeObject(obj_copy->address() + obj_copy->Size() / 2); CHECK(not_right != code); } @@ -106,41 +106,41 @@ TEST(HeapObjects) { InitializeVM(); v8::HandleScope sc; - Object* value = Heap::NumberFromDouble(1.000123)->ToObjectChecked(); + Object* value = HEAP->NumberFromDouble(1.000123)->ToObjectChecked(); CHECK(value->IsHeapNumber()); CHECK(value->IsNumber()); CHECK_EQ(1.000123, value->Number()); - value = Heap::NumberFromDouble(1.0)->ToObjectChecked(); + value = HEAP->NumberFromDouble(1.0)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(1.0, value->Number()); - value = Heap::NumberFromInt32(1024)->ToObjectChecked(); + value = HEAP->NumberFromInt32(1024)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(1024.0, value->Number()); - value = Heap::NumberFromInt32(Smi::kMinValue)->ToObjectChecked(); + value = HEAP->NumberFromInt32(Smi::kMinValue)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value()); - value = Heap::NumberFromInt32(Smi::kMaxValue)->ToObjectChecked(); + value = HEAP->NumberFromInt32(Smi::kMaxValue)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value()); #ifndef V8_TARGET_ARCH_X64 // TODO(lrn): We need a NumberFromIntptr function in order to test this. - value = Heap::NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked(); + value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked(); CHECK(value->IsHeapNumber()); CHECK(value->IsNumber()); CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number()); #endif MaybeObject* maybe_value = - Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1); + HEAP->NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1); value = maybe_value->ToObjectChecked(); CHECK(value->IsHeapNumber()); CHECK(value->IsNumber()); @@ -148,21 +148,22 @@ TEST(HeapObjects) { value->Number()); // nan oddball checks - CHECK(Heap::nan_value()->IsNumber()); - CHECK(isnan(Heap::nan_value()->Number())); + CHECK(HEAP->nan_value()->IsNumber()); + CHECK(isnan(HEAP->nan_value()->Number())); - Handle<String> s = Factory::NewStringFromAscii(CStrVector("fisk hest ")); + Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest ")); CHECK(s->IsString()); CHECK_EQ(10, s->length()); - String* object_symbol = String::cast(Heap::Object_symbol()); - CHECK(Top::context()->global()->HasLocalProperty(object_symbol)); + String* object_symbol = String::cast(HEAP->Object_symbol()); + CHECK( + Isolate::Current()->context()->global()->HasLocalProperty(object_symbol)); // Check ToString for oddballs - CheckOddball(Heap::true_value(), "true"); - CheckOddball(Heap::false_value(), "false"); - CheckOddball(Heap::null_value(), "null"); - CheckOddball(Heap::undefined_value(), "undefined"); + CheckOddball(HEAP->true_value(), "true"); + CheckOddball(HEAP->false_value(), "false"); + CheckOddball(HEAP->null_value(), "null"); + CheckOddball(HEAP->undefined_value(), "undefined"); // Check ToString for Smis CheckSmi(0, "0"); @@ -197,25 +198,25 @@ TEST(GarbageCollection) { v8::HandleScope sc; // Check GC. - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); - Handle<String> name = Factory::LookupAsciiSymbol("theFunction"); - Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); - Handle<String> prop_namex = Factory::LookupAsciiSymbol("theSlotx"); - Handle<String> obj_name = Factory::LookupAsciiSymbol("theObject"); + Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); + Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); + Handle<String> prop_namex = FACTORY->LookupAsciiSymbol("theSlotx"); + Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject"); { v8::HandleScope inner_scope; // Allocate a function and keep it in global object's property. Handle<JSFunction> function = - Factory::NewFunction(name, Factory::undefined_value()); + FACTORY->NewFunction(name, FACTORY->undefined_value()); Handle<Map> initial_map = - Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); - Top::context()->global()->SetProperty( + Isolate::Current()->context()->global()->SetProperty( *name, *function, NONE, kNonStrictMode)->ToObjectChecked(); // Allocate an object. Unrooted after leaving the scope. - Handle<JSObject> obj = Factory::NewJSObject(function); + Handle<JSObject> obj = FACTORY->NewJSObject(function); obj->SetProperty( *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); obj->SetProperty( @@ -225,34 +226,34 @@ TEST(GarbageCollection) { CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); } - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); // Function should be alive. - CHECK(Top::context()->global()->HasLocalProperty(*name)); + CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name)); // Check function is retained. - Object* func_value = - Top::context()->global()->GetProperty(*name)->ToObjectChecked(); + Object* func_value = Isolate::Current()->context()->global()-> + GetProperty(*name)->ToObjectChecked(); CHECK(func_value->IsJSFunction()); Handle<JSFunction> function(JSFunction::cast(func_value)); { HandleScope inner_scope; // Allocate another object, make it reachable from global. - Handle<JSObject> obj = Factory::NewJSObject(function); - Top::context()->global()->SetProperty( + Handle<JSObject> obj = FACTORY->NewJSObject(function); + Isolate::Current()->context()->global()->SetProperty( *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked(); obj->SetProperty( *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); } // After gc, it should survive. - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); - CHECK(Top::context()->global()->HasLocalProperty(*obj_name)); - CHECK(Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked()-> - IsJSObject()); - Object* obj = - Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked(); + CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name)); + CHECK(Isolate::Current()->context()->global()-> + GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); + Object* obj = Isolate::Current()->context()->global()-> + GetProperty(*obj_name)->ToObjectChecked(); JSObject* js_obj = JSObject::cast(obj); CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name)); } @@ -260,7 +261,7 @@ TEST(GarbageCollection) { static void VerifyStringAllocation(const char* string) { v8::HandleScope scope; - Handle<String> s = Factory::NewStringFromUtf8(CStrVector(string)); + Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string)); CHECK_EQ(StrLength(string), s->length()); for (int index = 0; index < s->length(); index++) { CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index)); @@ -284,12 +285,13 @@ TEST(LocalHandles) { v8::HandleScope scope; const char* name = "Kasper the spunky"; - Handle<String> string = Factory::NewStringFromAscii(CStrVector(name)); + Handle<String> string = FACTORY->NewStringFromAscii(CStrVector(name)); CHECK_EQ(StrLength(name), string->length()); } TEST(GlobalHandles) { + GlobalHandles* global_handles = Isolate::Current()->global_handles(); InitializeVM(); Handle<Object> h1; @@ -300,17 +302,17 @@ TEST(GlobalHandles) { { HandleScope scope; - Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk")); - Handle<Object> u = Factory::NewNumber(1.12344); + Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); + Handle<Object> u = FACTORY->NewNumber(1.12344); - h1 = GlobalHandles::Create(*i); - h2 = GlobalHandles::Create(*u); - h3 = GlobalHandles::Create(*i); - h4 = GlobalHandles::Create(*u); + h1 = global_handles->Create(*i); + h2 = global_handles->Create(*u); + h3 = global_handles->Create(*i); + h4 = global_handles->Create(*u); } // after gc, it should survive - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); CHECK((*h1)->IsString()); CHECK((*h2)->IsHeapNumber()); @@ -318,12 +320,12 @@ TEST(GlobalHandles) { CHECK((*h4)->IsHeapNumber()); CHECK_EQ(*h3, *h1); - GlobalHandles::Destroy(h1.location()); - GlobalHandles::Destroy(h3.location()); + global_handles->Destroy(h1.location()); + global_handles->Destroy(h3.location()); CHECK_EQ(*h4, *h2); - GlobalHandles::Destroy(h2.location()); - GlobalHandles::Destroy(h4.location()); + global_handles->Destroy(h2.location()); + global_handles->Destroy(h4.location()); } @@ -337,6 +339,7 @@ static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle, TEST(WeakGlobalHandlesScavenge) { + GlobalHandles* global_handles = Isolate::Current()->global_handles(); InitializeVM(); WeakPointerCleared = false; @@ -347,33 +350,34 @@ TEST(WeakGlobalHandlesScavenge) { { HandleScope scope; - Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk")); - Handle<Object> u = Factory::NewNumber(1.12344); + Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); + Handle<Object> u = FACTORY->NewNumber(1.12344); - h1 = GlobalHandles::Create(*i); - h2 = GlobalHandles::Create(*u); + h1 = global_handles->Create(*i); + h2 = global_handles->Create(*u); } - GlobalHandles::MakeWeak(h2.location(), - reinterpret_cast<void*>(1234), - &TestWeakGlobalHandleCallback); + global_handles->MakeWeak(h2.location(), + reinterpret_cast<void*>(1234), + &TestWeakGlobalHandleCallback); // Scavenge treats weak pointers as normal roots. - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK((*h1)->IsString()); CHECK((*h2)->IsHeapNumber()); CHECK(!WeakPointerCleared); - CHECK(!GlobalHandles::IsNearDeath(h2.location())); - CHECK(!GlobalHandles::IsNearDeath(h1.location())); + CHECK(!global_handles->IsNearDeath(h2.location())); + CHECK(!global_handles->IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); - GlobalHandles::Destroy(h2.location()); + global_handles->Destroy(h1.location()); + global_handles->Destroy(h2.location()); } TEST(WeakGlobalHandlesMark) { + GlobalHandles* global_handles = Isolate::Current()->global_handles(); InitializeVM(); WeakPointerCleared = false; @@ -384,34 +388,35 @@ TEST(WeakGlobalHandlesMark) { { HandleScope scope; - Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk")); - Handle<Object> u = Factory::NewNumber(1.12344); + Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); + Handle<Object> u = FACTORY->NewNumber(1.12344); - h1 = GlobalHandles::Create(*i); - h2 = GlobalHandles::Create(*u); + h1 = global_handles->Create(*i); + h2 = global_handles->Create(*u); } - Heap::CollectGarbage(OLD_POINTER_SPACE); - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(NEW_SPACE); // Make sure the object is promoted. - GlobalHandles::MakeWeak(h2.location(), - reinterpret_cast<void*>(1234), - &TestWeakGlobalHandleCallback); + global_handles->MakeWeak(h2.location(), + reinterpret_cast<void*>(1234), + &TestWeakGlobalHandleCallback); CHECK(!GlobalHandles::IsNearDeath(h1.location())); CHECK(!GlobalHandles::IsNearDeath(h2.location())); - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); CHECK((*h1)->IsString()); CHECK(WeakPointerCleared); CHECK(!GlobalHandles::IsNearDeath(h1.location())); - GlobalHandles::Destroy(h1.location()); + global_handles->Destroy(h1.location()); } TEST(DeleteWeakGlobalHandle) { + GlobalHandles* global_handles = Isolate::Current()->global_handles(); InitializeVM(); WeakPointerCleared = false; @@ -421,21 +426,21 @@ TEST(DeleteWeakGlobalHandle) { { HandleScope scope; - Handle<Object> i = Factory::NewStringFromAscii(CStrVector("fisk")); - h = GlobalHandles::Create(*i); + Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); + h = global_handles->Create(*i); } - GlobalHandles::MakeWeak(h.location(), - reinterpret_cast<void*>(1234), - &TestWeakGlobalHandleCallback); + global_handles->MakeWeak(h.location(), + reinterpret_cast<void*>(1234), + &TestWeakGlobalHandleCallback); // Scanvenge does not recognize weak reference. - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK(!WeakPointerCleared); // Mark-compact treats weak reference properly. - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); CHECK(WeakPointerCleared); } @@ -507,12 +512,12 @@ static const char* not_so_random_string_table[] = { static void CheckSymbols(const char** strings) { for (const char* string = *strings; *strings != 0; string = *strings++) { Object* a; - MaybeObject* maybe_a = Heap::LookupAsciiSymbol(string); + MaybeObject* maybe_a = HEAP->LookupAsciiSymbol(string); // LookupAsciiSymbol may return a failure if a GC is needed. if (!maybe_a->ToObject(&a)) continue; CHECK(a->IsSymbol()); Object* b; - MaybeObject *maybe_b = Heap::LookupAsciiSymbol(string); + MaybeObject* maybe_b = HEAP->LookupAsciiSymbol(string); if (!maybe_b->ToObject(&b)) continue; CHECK_EQ(b, a); CHECK(String::cast(b)->IsEqualTo(CStrVector(string))); @@ -532,15 +537,15 @@ TEST(FunctionAllocation) { InitializeVM(); v8::HandleScope sc; - Handle<String> name = Factory::LookupAsciiSymbol("theFunction"); + Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); Handle<JSFunction> function = - Factory::NewFunction(name, Factory::undefined_value()); + FACTORY->NewFunction(name, FACTORY->undefined_value()); Handle<Map> initial_map = - Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); - Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); - Handle<JSObject> obj = Factory::NewJSObject(function); + Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); + Handle<JSObject> obj = FACTORY->NewJSObject(function); obj->SetProperty( *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); @@ -555,14 +560,14 @@ TEST(ObjectProperties) { InitializeVM(); v8::HandleScope sc; - String* object_symbol = String::cast(Heap::Object_symbol()); - Object* raw_object = - Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked(); + String* object_symbol = String::cast(HEAP->Object_symbol()); + Object* raw_object = Isolate::Current()->context()->global()-> + GetProperty(object_symbol)->ToObjectChecked(); JSFunction* object_function = JSFunction::cast(raw_object); Handle<JSFunction> constructor(object_function); - Handle<JSObject> obj = Factory::NewJSObject(constructor); - Handle<String> first = Factory::LookupAsciiSymbol("first"); - Handle<String> second = Factory::LookupAsciiSymbol("second"); + Handle<JSObject> obj = FACTORY->NewJSObject(constructor); + Handle<String> first = FACTORY->LookupAsciiSymbol("first"); + Handle<String> second = FACTORY->LookupAsciiSymbol("second"); // check for empty CHECK(!obj->HasLocalProperty(*first)); @@ -608,18 +613,18 @@ TEST(ObjectProperties) { // check string and symbol match static const char* string1 = "fisk"; - Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1)); + Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1)); obj->SetProperty( *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1); + Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1); CHECK(obj->HasLocalProperty(*s1_symbol)); // check symbol and string match static const char* string2 = "fugl"; - Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2); + Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2); obj->SetProperty( *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2)); + Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2)); CHECK(obj->HasLocalProperty(*s2)); } @@ -628,15 +633,15 @@ TEST(JSObjectMaps) { InitializeVM(); v8::HandleScope sc; - Handle<String> name = Factory::LookupAsciiSymbol("theFunction"); + Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); Handle<JSFunction> function = - Factory::NewFunction(name, Factory::undefined_value()); + FACTORY->NewFunction(name, FACTORY->undefined_value()); Handle<Map> initial_map = - Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); - Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); - Handle<JSObject> obj = Factory::NewJSObject(function); + Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); + Handle<JSObject> obj = FACTORY->NewJSObject(function); // Set a propery obj->SetProperty( @@ -652,14 +657,14 @@ TEST(JSArray) { InitializeVM(); v8::HandleScope sc; - Handle<String> name = Factory::LookupAsciiSymbol("Array"); - Object* raw_object = - Top::context()->global()->GetProperty(*name)->ToObjectChecked(); + Handle<String> name = FACTORY->LookupAsciiSymbol("Array"); + Object* raw_object = Isolate::Current()->context()->global()-> + GetProperty(*name)->ToObjectChecked(); Handle<JSFunction> function = Handle<JSFunction>( JSFunction::cast(raw_object)); // Allocate the object. - Handle<JSObject> object = Factory::NewJSObject(function); + 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(); @@ -670,13 +675,13 @@ TEST(JSArray) { CHECK(array->HasFastElements()); // Must be in fast mode. // array[length] = name. - ok = array->SetElement(0, *name)->ToObjectChecked(); + ok = array->SetElement(0, *name, kNonStrictMode, true)->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); + FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); ok = array->SetElementsLength(*length)->ToObjectChecked(); uint32_t int_length = 0; @@ -685,7 +690,8 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - ok = array->SetElement(int_length, *name)->ToObjectChecked(); + ok = array->SetElement( + int_length, *name, kNonStrictMode, true)->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); @@ -698,23 +704,24 @@ TEST(JSObjectCopy) { InitializeVM(); v8::HandleScope sc; - String* object_symbol = String::cast(Heap::Object_symbol()); - Object* raw_object = - Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked(); + String* object_symbol = String::cast(HEAP->Object_symbol()); + Object* raw_object = Isolate::Current()->context()->global()-> + GetProperty(object_symbol)->ToObjectChecked(); JSFunction* object_function = JSFunction::cast(raw_object); Handle<JSFunction> constructor(object_function); - Handle<JSObject> obj = Factory::NewJSObject(constructor); - Handle<String> first = Factory::LookupAsciiSymbol("first"); - Handle<String> second = Factory::LookupAsciiSymbol("second"); + Handle<JSObject> obj = FACTORY->NewJSObject(constructor); + Handle<String> first = FACTORY->LookupAsciiSymbol("first"); + Handle<String> second = FACTORY->LookupAsciiSymbol("second"); obj->SetProperty( *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); obj->SetProperty( *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); - Object* ok = obj->SetElement(0, *first)->ToObjectChecked(); + Object* ok = + obj->SetElement(0, *first, kNonStrictMode, true)->ToObjectChecked(); - ok = obj->SetElement(1, *second)->ToObjectChecked(); + ok = obj->SetElement(1, *second, kNonStrictMode, true)->ToObjectChecked(); // Make the clone. Handle<JSObject> clone = Copy(obj); @@ -732,8 +739,8 @@ TEST(JSObjectCopy) { clone->SetProperty( *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - ok = clone->SetElement(0, *second)->ToObjectChecked(); - ok = clone->SetElement(1, *first)->ToObjectChecked(); + ok = clone->SetElement(0, *second, kNonStrictMode, true)->ToObjectChecked(); + ok = clone->SetElement(1, *first, kNonStrictMode, true)->ToObjectChecked(); CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); @@ -761,17 +768,17 @@ TEST(StringAllocation) { non_ascii[3 * i + 2] = chars[2]; } Handle<String> non_ascii_sym = - Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length)); + FACTORY->LookupSymbol(Vector<const char>(non_ascii, 3 * length)); CHECK_EQ(length, non_ascii_sym->length()); Handle<String> ascii_sym = - Factory::LookupSymbol(Vector<const char>(ascii, length)); + FACTORY->LookupSymbol(Vector<const char>(ascii, length)); CHECK_EQ(length, ascii_sym->length()); Handle<String> non_ascii_str = - Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length)); + FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length)); non_ascii_str->Hash(); CHECK_EQ(length, non_ascii_str->length()); Handle<String> ascii_str = - Factory::NewStringFromUtf8(Vector<const char>(ascii, length)); + FACTORY->NewStringFromUtf8(Vector<const char>(ascii, length)); ascii_str->Hash(); CHECK_EQ(length, ascii_str->length()); DeleteArray(non_ascii); @@ -805,22 +812,22 @@ TEST(Iteration) { int next_objs_index = 0; // 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); + objs[next_objs_index++] = FACTORY->NewJSArray(10, TENURED); // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE objs[next_objs_index++] = - Factory::NewStringFromAscii(CStrVector("abcdefghij")); + FACTORY->NewStringFromAscii(CStrVector("abcdefghij")); objs[next_objs_index++] = - Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED); + FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED); // Allocate a large string (for large object space). - int large_size = Heap::MaxObjectSizeInPagedSpace() + 1; + int large_size = HEAP->MaxObjectSizeInPagedSpace() + 1; char* str = new char[large_size]; for (int i = 0; i < large_size - 1; ++i) str[i] = 'a'; str[large_size - 1] = '\0'; objs[next_objs_index++] = - Factory::NewStringFromAscii(CStrVector(str), TENURED); + FACTORY->NewStringFromAscii(CStrVector(str), TENURED); delete[] str; // Add a Map object to look for. @@ -834,9 +841,9 @@ TEST(Iteration) { TEST(LargeObjectSpaceContains) { InitializeVM(); - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); - Address current_top = Heap::new_space()->top(); + 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; @@ -859,7 +866,7 @@ TEST(LargeObjectSpaceContains) { kPointerSize; CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements)); FixedArray* array = FixedArray::cast( - Heap::AllocateFixedArray(n_elements)->ToObjectChecked()); + HEAP->AllocateFixedArray(n_elements)->ToObjectChecked()); int index = n_elements - 1; CHECK_EQ(flags_ptr, @@ -869,8 +876,8 @@ TEST(LargeObjectSpaceContains) { // 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)); + CHECK(HEAP->new_space()->Contains(addr)); + CHECK(!HEAP->lo_space()->Contains(addr)); } @@ -901,7 +908,7 @@ TEST(Regression39128) { // Increase the chance of 'bump-the-pointer' allocation in old space. bool force_compaction = true; - Heap::CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(force_compaction); v8::HandleScope scope; @@ -910,11 +917,12 @@ TEST(Regression39128) { // that region dirty marks are updated correctly. // Step 1: prepare a map for the object. We add 1 inobject property to it. - Handle<JSFunction> object_ctor(Top::global_context()->object_function()); + Handle<JSFunction> object_ctor( + Isolate::Current()->global_context()->object_function()); CHECK(object_ctor->has_initial_map()); Handle<Map> object_map(object_ctor->initial_map()); // Create a map with single inobject property. - Handle<Map> my_map = Factory::CopyMap(object_map, 1); + Handle<Map> my_map = FACTORY->CopyMap(object_map, 1); int n_properties = my_map->inobject_properties(); CHECK_GT(n_properties, 0); @@ -924,15 +932,15 @@ TEST(Regression39128) { // just enough room to allocate JSObject and thus fill the newspace. int allocation_amount = Min(FixedArray::kMaxSize, - Heap::MaxObjectSizeInNewSpace()); + HEAP->MaxObjectSizeInNewSpace()); int allocation_len = LenFromSize(allocation_amount); - NewSpace* new_space = Heap::new_space(); + NewSpace* new_space = HEAP->new_space(); Address* top_addr = new_space->allocation_top_address(); Address* limit_addr = new_space->allocation_limit_address(); while ((*limit_addr - *top_addr) > allocation_amount) { - CHECK(!Heap::always_allocate()); - Object* array = - Heap::AllocateFixedArray(allocation_len)->ToObjectChecked(); + CHECK(!HEAP->always_allocate()); + Object* array = HEAP->AllocateFixedArray(allocation_len)->ToObjectChecked(); + CHECK(!array->IsFailure()); CHECK(new_space->Contains(array)); } @@ -941,12 +949,12 @@ TEST(Regression39128) { int fixed_array_len = LenFromSize(to_fill); CHECK(fixed_array_len < FixedArray::kMaxLength); - CHECK(!Heap::always_allocate()); - Object* array = - Heap::AllocateFixedArray(fixed_array_len)->ToObjectChecked(); + CHECK(!HEAP->always_allocate()); + Object* array = HEAP->AllocateFixedArray(fixed_array_len)->ToObjectChecked(); + CHECK(!array->IsFailure()); CHECK(new_space->Contains(array)); - Object* object = Heap::AllocateJSObjectFromMap(*my_map)->ToObjectChecked(); + Object* object = HEAP->AllocateJSObjectFromMap(*my_map)->ToObjectChecked(); CHECK(new_space->Contains(object)); JSObject* jsobject = JSObject::cast(object); CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length()); @@ -958,15 +966,15 @@ TEST(Regression39128) { // Step 4: clone jsobject, but force always allocate first to create a clone // in old pointer space. - Address old_pointer_space_top = Heap::old_pointer_space()->top(); + Address old_pointer_space_top = HEAP->old_pointer_space()->top(); AlwaysAllocateScope aa_scope; - Object* clone_obj = Heap::CopyJSObject(jsobject)->ToObjectChecked(); + Object* clone_obj = HEAP->CopyJSObject(jsobject)->ToObjectChecked(); JSObject* clone = JSObject::cast(clone_obj); if (clone->address() != old_pointer_space_top) { // Alas, got allocated from free list, we cannot do checks. return; } - CHECK(Heap::old_pointer_space()->Contains(clone->address())); + CHECK(HEAP->old_pointer_space()->Contains(clone->address())); // Step 5: verify validity of region dirty marks. Address clone_addr = clone->address(); @@ -988,7 +996,7 @@ TEST(TestCodeFlushing) { " var z = x + y;" "};" "foo()"; - Handle<String> foo_name = Factory::LookupAsciiSymbol("foo"); + Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); // This compile will add the code to the compilation cache. { v8::HandleScope scope; @@ -996,23 +1004,23 @@ TEST(TestCodeFlushing) { } // Check function is compiled. - Object* func_value = - Top::context()->global()->GetProperty(*foo_name)->ToObjectChecked(); + Object* func_value = Isolate::Current()->context()->global()-> + GetProperty(*foo_name)->ToObjectChecked(); CHECK(func_value->IsJSFunction()); Handle<JSFunction> function(JSFunction::cast(func_value)); CHECK(function->shared()->is_compiled()); - Heap::CollectAllGarbage(true); - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); 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(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); // foo should no longer be in the compilation cache CHECK(!function->shared()->is_compiled() || function->IsOptimized()); @@ -1027,7 +1035,7 @@ TEST(TestCodeFlushing) { // Count the number of global contexts in the weak list of global contexts. static int CountGlobalContexts() { int count = 0; - Object* object = Heap::global_contexts_list(); + Object* object = HEAP->global_contexts_list(); while (!object->IsUndefined()) { count++; object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); @@ -1051,6 +1059,8 @@ static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) { TEST(TestInternalWeakLists) { + v8::V8::Initialize(); + static const int kNumTestContexts = 10; v8::HandleScope scope; @@ -1094,35 +1104,35 @@ TEST(TestInternalWeakLists) { // Scavenge treats these references as strong. for (int j = 0; j < 10; j++) { - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); } // Mark compact handles the weak references. - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); // Get rid of f3 and f5 in the same way. CompileRun("f3=null"); for (int j = 0; j < 10; j++) { - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); } - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); CompileRun("f5=null"); for (int j = 0; j < 10; j++) { - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); } - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); ctx[i]->Exit(); } // Force compilation cache cleanup. - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); // Dispose the global contexts one by one. for (int i = 0; i < kNumTestContexts; i++) { @@ -1131,12 +1141,12 @@ TEST(TestInternalWeakLists) { // Scavenge treats these references as strong. for (int j = 0; j < 10; j++) { - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK_EQ(kNumTestContexts - i, CountGlobalContexts()); } // Mark compact handles the weak references. - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); } @@ -1148,10 +1158,10 @@ TEST(TestInternalWeakLists) { // causing a GC after the specified number of elements. static int CountGlobalContextsWithGC(int n) { int count = 0; - Handle<Object> object(Heap::global_contexts_list()); + Handle<Object> object(HEAP->global_contexts_list()); while (!object->IsUndefined()) { count++; - if (count == n) Heap::CollectAllGarbage(true); + if (count == n) HEAP->CollectAllGarbage(true); object = Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); } @@ -1170,7 +1180,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(true); object = Handle<Object>( Object::cast(JSFunction::cast(*object)->next_function_link())); } @@ -1179,6 +1189,8 @@ static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, TEST(TestInternalWeakListsTraverseWithGC) { + v8::V8::Initialize(); + static const int kNumTestContexts = 10; v8::HandleScope scope; @@ -1228,7 +1240,7 @@ TEST(TestInternalWeakListsTraverseWithGC) { TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { InitializeVM(); - intptr_t size_of_objects_1 = Heap::SizeOfObjects(); + intptr_t size_of_objects_1 = HEAP->SizeOfObjects(); HeapIterator iterator(HeapIterator::kFilterFreeListNodes); intptr_t size_of_objects_2 = 0; for (HeapObject* obj = iterator.next(); @@ -1283,10 +1295,10 @@ TEST(HeapIteratorFilterUnreachable) { InitializeVM(); v8::HandleScope scope; CompileRun("a = {}; b = {};"); - v8::Handle<Object> a(Top::context()->global()->GetProperty( - *Factory::LookupAsciiSymbol("a"))->ToObjectChecked()); - v8::Handle<Object> b(Top::context()->global()->GetProperty( - *Factory::LookupAsciiSymbol("b"))->ToObjectChecked()); + 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); { HeapIteratorTestHelper helper(*a, *b); @@ -1294,8 +1306,8 @@ TEST(HeapIteratorFilterUnreachable) { CHECK(helper.a_found()); CHECK(helper.b_found()); } - CHECK(Top::context()->global()->DeleteProperty( - *Factory::LookupAsciiSymbol("a"), JSObject::FORCE_DELETION)); + 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; diff --git a/deps/v8/test/cctest/test-liveedit.cc b/deps/v8/test/cctest/test-liveedit.cc index 244980a19..2498fca90 100644 --- a/deps/v8/test/cctest/test-liveedit.cc +++ b/deps/v8/test/cctest/test-liveedit.cc @@ -44,13 +44,13 @@ class StringCompareInput : public Comparator::Input { public: StringCompareInput(const char* s1, const char* s2) : s1_(s1), s2_(s2) { } - int getLength1() { + int GetLength1() { return StrLength(s1_); } - int getLength2() { + int GetLength2() { return StrLength(s2_); } - bool equals(int index1, int index2) { + bool Equals(int index1, int index2) { return s1_[index1] == s2_[index2]; } @@ -95,7 +95,7 @@ void CompareStringsOneWay(const char* s1, const char* s2, int expected_diff_parameter = -1) { StringCompareInput input(s1, s2); - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); DiffChunkStruct* first_chunk; ListDiffOutputWriter writer(&first_chunk); @@ -158,6 +158,7 @@ void CompareStrings(const char* s1, const char* s2, // --- T h e A c t u a l T e s t s TEST(LiveEditDiffer) { + v8::internal::V8::Initialize(NULL); CompareStrings("zz1zzz12zz123zzz", "zzzzzzzzzz", 6); CompareStrings("zz1zzz12zz123zzz", "zz0zzz0zz0zzz", 9); CompareStrings("123456789", "987654321", 16); diff --git a/deps/v8/test/cctest/test-lockers.cc b/deps/v8/test/cctest/test-lockers.cc new file mode 100644 index 000000000..4579361f3 --- /dev/null +++ b/deps/v8/test/cctest/test-lockers.cc @@ -0,0 +1,629 @@ +// Copyright 2007-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 <limits.h> + +#include "v8.h" + +#include "api.h" +#include "isolate.h" +#include "compilation-cache.h" +#include "execution.h" +#include "snapshot.h" +#include "platform.h" +#include "utils.h" +#include "cctest.h" +#include "parser.h" +#include "unicode-inl.h" + +using ::v8::AccessorInfo; +using ::v8::Context; +using ::v8::Extension; +using ::v8::Function; +using ::v8::HandleScope; +using ::v8::Local; +using ::v8::Object; +using ::v8::ObjectTemplate; +using ::v8::Persistent; +using ::v8::Script; +using ::v8::String; +using ::v8::Value; +using ::v8::V8; + +namespace i = ::i; + + + + +// Migrating an isolate +class KangarooThread : public v8::internal::Thread { + public: + KangarooThread(v8::Isolate* isolate, + v8::Handle<v8::Context> context, int value) + : Thread("KangarooThread"), + isolate_(isolate), context_(context), value_(value) { + } + + void Run() { + { + v8::Locker locker(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + CHECK_EQ(isolate_, v8::internal::Isolate::Current()); + v8::HandleScope scope; + v8::Context::Scope context_scope(context_); + Local<Value> v = CompileRun("getValue()"); + CHECK(v->IsNumber()); + CHECK_EQ(30, static_cast<int>(v->NumberValue())); + } + { + v8::Locker locker(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::Context::Scope context_scope(context_); + v8::HandleScope scope; + Local<Value> v = CompileRun("getValue()"); + CHECK(v->IsNumber()); + CHECK_EQ(30, static_cast<int>(v->NumberValue())); + } + isolate_->Dispose(); + } + + private: + v8::Isolate* isolate_; + Persistent<v8::Context> context_; + int value_; +}; + +// Migrates an isolate from one thread to another +TEST(KangarooIsolates) { + v8::Isolate* isolate = v8::Isolate::New(); + Persistent<v8::Context> context; + { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + context = v8::Context::New(); + v8::Context::Scope context_scope(context); + CHECK_EQ(isolate, v8::internal::Isolate::Current()); + CompileRun("function getValue() { return 30; }"); + } + KangarooThread thread1(isolate, context, 1); + thread1.Start(); + thread1.Join(); +} + +static void CalcFibAndCheck() { + Local<Value> v = CompileRun("function fib(n) {" + " if (n <= 2) return 1;" + " return fib(n-1) + fib(n-2);" + "}" + "fib(10)"); + CHECK(v->IsNumber()); + CHECK_EQ(55, static_cast<int>(v->NumberValue())); +} + +class JoinableThread { + public: + explicit JoinableThread(const char* name) + : name_(name), + semaphore_(i::OS::CreateSemaphore(0)), + thread_(this) { + } + + virtual ~JoinableThread() { + delete semaphore_; + } + + void Start() { + thread_.Start(); + } + + void Join() { + semaphore_->Wait(); + } + + virtual void Run() = 0; + private: + class ThreadWithSemaphore : public i::Thread { + public: + explicit ThreadWithSemaphore(JoinableThread* joinable_thread) + : Thread(joinable_thread->name_), + joinable_thread_(joinable_thread) { + } + + virtual void Run() { + joinable_thread_->Run(); + joinable_thread_->semaphore_->Signal(); + } + + private: + JoinableThread* joinable_thread_; + }; + + const char* name_; + i::Semaphore* semaphore_; + ThreadWithSemaphore thread_; + + friend class ThreadWithSemaphore; + + DISALLOW_COPY_AND_ASSIGN(JoinableThread); +}; + + +class IsolateLockingThreadWithLocalContext : public JoinableThread { + public: + explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate) + : JoinableThread("IsolateLockingThread"), + isolate_(isolate) { + } + + virtual void Run() { + v8::Locker locker(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + LocalContext local_context; + CHECK_EQ(isolate_, v8::internal::Isolate::Current()); + CalcFibAndCheck(); + } + private: + v8::Isolate* isolate_; +}; + +static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { + for (int i = 0; i < threads.length(); i++) { + threads[i]->Start(); + } + for (int i = 0; i < threads.length(); i++) { + threads[i]->Join(); + } + for (int i = 0; i < threads.length(); i++) { + delete threads[i]; + } +} + + +// Run many threads all locking on the same isolate +TEST(IsolateLockingStress) { + const int kNThreads = 100; + i::List<JoinableThread*> threads(kNThreads); + v8::Isolate* isolate = v8::Isolate::New(); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new IsolateLockingThreadWithLocalContext(isolate)); + } + StartJoinAndDeleteThreads(threads); + isolate->Dispose(); +} + +class IsolateNonlockingThread : public JoinableThread { + public: + explicit IsolateNonlockingThread() + : JoinableThread("IsolateNonlockingThread") { + } + + virtual void Run() { + v8::Isolate* isolate = v8::Isolate::New(); + { + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + v8::Handle<v8::Context> context = v8::Context::New(); + v8::Context::Scope context_scope(context); + CHECK_EQ(isolate, v8::internal::Isolate::Current()); + CalcFibAndCheck(); + } + isolate->Dispose(); + } + private: +}; + +// Run many threads each accessing its own isolate without locking +TEST(MultithreadedParallelIsolates) { +#ifdef V8_TARGET_ARCH_ARM + const int kNThreads = 10; +#else + const int kNThreads = 50; +#endif + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new IsolateNonlockingThread()); + } + StartJoinAndDeleteThreads(threads); +} + + +class IsolateNestedLockingThread : public JoinableThread { + public: + explicit IsolateNestedLockingThread(v8::Isolate* isolate) + : JoinableThread("IsolateNestedLocking"), isolate_(isolate) { + } + virtual void Run() { + v8::Locker lock(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + LocalContext local_context; + { + v8::Locker another_lock(isolate_); + CalcFibAndCheck(); + } + { + v8::Locker another_lock(isolate_); + CalcFibAndCheck(); + } + } + private: + v8::Isolate* isolate_; +}; + +// Run many threads with nested locks +TEST(IsolateNestedLocking) { + const int kNThreads = 100; + v8::Isolate* isolate = v8::Isolate::New(); + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new IsolateNestedLockingThread(isolate)); + } + StartJoinAndDeleteThreads(threads); +} + + +class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread { + public: + SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1, + v8::Isolate* isolate2) + : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"), + isolate1_(isolate1), isolate2_(isolate2) { + } + + virtual void Run() { + v8::Locker lock(isolate1_); + v8::Isolate::Scope isolate_scope(isolate1_); + v8::HandleScope handle_scope; + LocalContext local_context; + + IsolateLockingThreadWithLocalContext threadB(isolate2_); + threadB.Start(); + CalcFibAndCheck(); + threadB.Join(); + } + private: + v8::Isolate* isolate1_; + v8::Isolate* isolate2_; +}; + +// Run parallel threads that lock and access different isolates in parallel +TEST(SeparateIsolatesLocksNonexclusive) { + const int kNThreads = 100; + v8::Isolate* isolate1 = v8::Isolate::New(); + v8::Isolate* isolate2 = v8::Isolate::New(); + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new SeparateIsolatesLocksNonexclusiveThread(isolate1, + isolate2)); + } + StartJoinAndDeleteThreads(threads); + isolate2->Dispose(); + isolate1->Dispose(); +} + +class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread { + public: + explicit LockIsolateAndCalculateFibSharedContextThread( + v8::Isolate* isolate, v8::Handle<v8::Context> context) + : JoinableThread("LockIsolateAndCalculateFibThread"), + isolate_(isolate), + context_(context) { + } + + virtual void Run() { + v8::Locker lock(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope; + v8::Context::Scope context_scope(context_); + CalcFibAndCheck(); + } + private: + v8::Isolate* isolate_; + Persistent<v8::Context> context_; +}; + +class LockerUnlockerThread : public JoinableThread { + public: + explicit LockerUnlockerThread(v8::Isolate* isolate) + : JoinableThread("LockerUnlockerThread"), + isolate_(isolate) { + } + + virtual void Run() { + v8::Locker lock(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + v8::Handle<v8::Context> context = v8::Context::New(); + { + v8::Context::Scope context_scope(context); + CalcFibAndCheck(); + } + { + isolate_->Exit(); + v8::Unlocker unlocker(isolate_); + LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); + thread.Start(); + thread.Join(); + } + isolate_->Enter(); + { + v8::Context::Scope context_scope(context); + CalcFibAndCheck(); + } + } + private: + v8::Isolate* isolate_; +}; + +// Use unlocker inside of a Locker, multiple threads. +TEST(LockerUnlocker) { + const int kNThreads = 100; + i::List<JoinableThread*> threads(kNThreads); + v8::Isolate* isolate = v8::Isolate::New(); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new LockerUnlockerThread(isolate)); + } + StartJoinAndDeleteThreads(threads); + isolate->Dispose(); +} + +class LockTwiceAndUnlockThread : public JoinableThread { + public: + explicit LockTwiceAndUnlockThread(v8::Isolate* isolate) + : JoinableThread("LockTwiceAndUnlockThread"), + isolate_(isolate) { + } + + virtual void Run() { + v8::Locker lock(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + v8::Handle<v8::Context> context = v8::Context::New(); + { + v8::Context::Scope context_scope(context); + CalcFibAndCheck(); + } + { + v8::Locker second_lock(isolate_); + { + isolate_->Exit(); + v8::Unlocker unlocker(isolate_); + LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); + thread.Start(); + thread.Join(); + } + } + isolate_->Enter(); + { + v8::Context::Scope context_scope(context); + CalcFibAndCheck(); + } + } + private: + v8::Isolate* isolate_; +}; + +// Use Unlocker inside two Lockers. +TEST(LockTwiceAndUnlock) { + const int kNThreads = 100; + i::List<JoinableThread*> threads(kNThreads); + v8::Isolate* isolate = v8::Isolate::New(); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new LockTwiceAndUnlockThread(isolate)); + } + StartJoinAndDeleteThreads(threads); + isolate->Dispose(); +} + +class LockAndUnlockDifferentIsolatesThread : public JoinableThread { + public: + LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1, + v8::Isolate* isolate2) + : JoinableThread("LockAndUnlockDifferentIsolatesThread"), + isolate1_(isolate1), + isolate2_(isolate2) { + } + + virtual void Run() { + Persistent<v8::Context> context1; + Persistent<v8::Context> context2; + v8::Locker lock1(isolate1_); + CHECK(v8::Locker::IsLocked(isolate1_)); + CHECK(!v8::Locker::IsLocked(isolate2_)); + { + v8::Isolate::Scope isolate_scope(isolate1_); + v8::HandleScope handle_scope; + context1 = v8::Context::New(); + { + v8::Context::Scope context_scope(context1); + CalcFibAndCheck(); + } + } + v8::Locker lock2(isolate2_); + CHECK(v8::Locker::IsLocked(isolate1_)); + CHECK(v8::Locker::IsLocked(isolate2_)); + { + v8::Isolate::Scope isolate_scope(isolate2_); + v8::HandleScope handle_scope; + context2 = v8::Context::New(); + { + v8::Context::Scope context_scope(context2); + CalcFibAndCheck(); + } + } + { + v8::Unlocker unlock1(isolate1_); + CHECK(!v8::Locker::IsLocked(isolate1_)); + CHECK(v8::Locker::IsLocked(isolate2_)); + v8::Isolate::Scope isolate_scope(isolate2_); + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(context2); + LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1); + thread.Start(); + CalcFibAndCheck(); + thread.Join(); + } + } + private: + v8::Isolate* isolate1_; + v8::Isolate* isolate2_; +}; + +// Lock two isolates and unlock one of them. +TEST(LockAndUnlockDifferentIsolates) { + v8::Isolate* isolate1 = v8::Isolate::New(); + v8::Isolate* isolate2 = v8::Isolate::New(); + LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2); + thread.Start(); + thread.Join(); + isolate2->Dispose(); + isolate1->Dispose(); +} + +class LockUnlockLockThread : public JoinableThread { + public: + LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context) + : JoinableThread("LockUnlockLockThread"), + isolate_(isolate), + context_(context) { + } + + virtual void Run() { + v8::Locker lock1(isolate_); + CHECK(v8::Locker::IsLocked(isolate_)); + CHECK(!v8::Locker::IsLocked()); + { + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(context_); + CalcFibAndCheck(); + } + { + v8::Unlocker unlock1(isolate_); + CHECK(!v8::Locker::IsLocked(isolate_)); + CHECK(!v8::Locker::IsLocked()); + { + v8::Locker lock2(isolate_); + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope; + CHECK(v8::Locker::IsLocked(isolate_)); + CHECK(!v8::Locker::IsLocked()); + v8::Context::Scope context_scope(context_); + CalcFibAndCheck(); + } + } + } + + private: + v8::Isolate* isolate_; + v8::Persistent<v8::Context> context_; +}; + +// Locker inside an Unlocker inside a Locker. +TEST(LockUnlockLockMultithreaded) { + const int kNThreads = 100; + v8::Isolate* isolate = v8::Isolate::New(); + Persistent<v8::Context> context; + { + v8::Locker locker_(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + context = v8::Context::New(); + } + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new LockUnlockLockThread(isolate, context)); + } + StartJoinAndDeleteThreads(threads); +} + +class LockUnlockLockDefaultIsolateThread : public JoinableThread { + public: + explicit LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context) + : JoinableThread("LockUnlockLockDefaultIsolateThread"), + context_(context) { + } + + virtual void Run() { + v8::Locker lock1; + { + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(context_); + CalcFibAndCheck(); + } + { + v8::Unlocker unlock1; + { + v8::Locker lock2; + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(context_); + CalcFibAndCheck(); + } + } + } + + private: + v8::Persistent<v8::Context> context_; +}; + +// Locker inside an Unlocker inside a Locker for default isolate. +TEST(LockUnlockLockDefaultIsolateMultithreaded) { + const int kNThreads = 100; + Persistent<v8::Context> context; + { + v8::Locker locker_; + v8::HandleScope handle_scope; + context = v8::Context::New(); + } + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new LockUnlockLockDefaultIsolateThread(context)); + } + StartJoinAndDeleteThreads(threads); +} + + +TEST(Regress1433) { + for (int i = 0; i < 10; i++) { + v8::Isolate* isolate = v8::Isolate::New(); + { + v8::Locker lock(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope; + v8::Persistent<Context> context = v8::Context::New(); + v8::Context::Scope context_scope(context); + v8::Handle<String> source = v8::String::New("1+1"); + v8::Handle<Script> script = v8::Script::Compile(source); + v8::Handle<Value> result = script->Run(); + v8::String::AsciiValue ascii(result); + context.Dispose(); + } + isolate->Dispose(); + } +} diff --git a/deps/v8/test/cctest/test-log-stack-tracer.cc b/deps/v8/test/cctest/test-log-stack-tracer.cc index bf72184fb..b967c7388 100644 --- a/deps/v8/test/cctest/test-log-stack-tracer.cc +++ b/deps/v8/test/cctest/test-log-stack-tracer.cc @@ -1,4 +1,4 @@ -// Copyright 2010 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: @@ -36,10 +36,9 @@ #include "api.h" #include "codegen.h" #include "log.h" -#include "top.h" +#include "isolate.h" #include "cctest.h" #include "disassembler.h" -#include "register-allocator-inl.h" #include "vm-state-inl.h" using v8::Function; @@ -52,10 +51,10 @@ using v8::Value; using v8::internal::byte; using v8::internal::Address; using v8::internal::Handle; +using v8::internal::Isolate; using v8::internal::JSFunction; using v8::internal::StackTracer; using v8::internal::TickSample; -using v8::internal::Top; namespace i = v8::internal; @@ -78,18 +77,19 @@ static void DoTrace(Address fp) { // sp is only used to define stack high bound trace_env.sample->sp = reinterpret_cast<Address>(trace_env.sample) - 10240; - StackTracer::Trace(trace_env.sample); + StackTracer::Trace(Isolate::Current(), trace_env.sample); } // Hide c_entry_fp to emulate situation when sampling is done while // pure JS code is being executed static void DoTraceHideCEntryFPAddress(Address fp) { - v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address()); + v8::internal::Address saved_c_frame_fp = + *(Isolate::Current()->c_entry_fp_address()); CHECK(saved_c_frame_fp); - *(Top::c_entry_fp_address()) = 0; + *(Isolate::Current()->c_entry_fp_address()) = 0; DoTrace(fp); - *(Top::c_entry_fp_address()) = saved_c_frame_fp; + *(Isolate::Current()->c_entry_fp_address()) = saved_c_frame_fp; } @@ -163,8 +163,8 @@ v8::Handle<v8::Value> TraceExtension::JSTrace(const v8::Arguments& args) { static Address GetJsEntrySp() { - CHECK_NE(NULL, Top::GetCurrentThread()); - return Top::js_entry_sp(Top::GetCurrentThread()); + CHECK_NE(NULL, i::Isolate::Current()->thread_local_top()); + return Isolate::js_entry_sp(i::Isolate::Current()->thread_local_top()); } @@ -276,9 +276,12 @@ static void CreateTraceCallerFunction(const char* func_name, // This test verifies that stack tracing works when called during // execution of a native function called from JS code. In this case, -// StackTracer uses Top::c_entry_fp as a starting point for stack +// StackTracer uses Isolate::c_entry_fp as a starting point for stack // walking. TEST(CFromJSStackTrace) { + // BUG(1303) Inlining of JSFuncDoTrace() in JSTrace below breaks this test. + i::FLAG_use_inlining = false; + TickSample sample; InitTraceEnv(&sample); @@ -302,13 +305,11 @@ TEST(CFromJSStackTrace) { // DoTrace(EBP) [native] // StackTracer::Trace - // The VM state tracking keeps track of external callbacks and puts - // them at the top of the sample stack. - int base = 0; - CHECK(sample.stack[0] == FUNCTION_ADDR(TraceExtension::Trace)); - base++; + CHECK(sample.has_external_callback); + CHECK_EQ(FUNCTION_ADDR(TraceExtension::Trace), sample.external_callback); // 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])); @@ -318,7 +319,7 @@ TEST(CFromJSStackTrace) { // This test verifies that stack tracing works when called during // execution of JS code. However, as calling StackTracer requires // entering native code, we can only emulate pure JS by erasing -// Top::c_entry_fp value. In this case, StackTracer uses passed frame +// Isolate::c_entry_fp value. In this case, StackTracer uses passed frame // pointer value as a starting point for stack walking. TEST(PureJSStackTrace) { // This test does not pass with inlining enabled since inlined functions @@ -353,13 +354,11 @@ TEST(PureJSStackTrace) { // StackTracer::Trace // - // The VM state tracking keeps track of external callbacks and puts - // them at the top of the sample stack. - int base = 0; - CHECK(sample.stack[0] == FUNCTION_ADDR(TraceExtension::JSTrace)); - base++; + CHECK(sample.has_external_callback); + CHECK_EQ(FUNCTION_ADDR(TraceExtension::JSTrace), sample.external_callback); // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" + int base = 0; CHECK_GT(sample.frames_count, base + 1); CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 0])); CHECK(IsAddressWithinFuncCode("OuterJSTrace", sample.stack[base + 1])); @@ -397,6 +396,7 @@ static int CFunc(int depth) { TEST(PureCStackTrace) { TickSample sample; InitTraceEnv(&sample); + InitializeVM(); // Check that sampler doesn't crash CHECK_EQ(10, CFunc(10)); } diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 30b8a48db..e7a178cc5 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/deps/v8/test/cctest/test-log.cc @@ -29,61 +29,61 @@ static void SetUp() { // Log to memory buffer. i::FLAG_logfile = "*"; i::FLAG_log = true; - Logger::Setup(); + LOGGER->Setup(); } static void TearDown() { - Logger::TearDown(); + LOGGER->TearDown(); } TEST(EmptyLog) { SetUp(); - CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0)); - CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0)); - CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100)); - CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100)); + CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0)); + CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 0)); + CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 100)); + CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 100)); TearDown(); } TEST(GetMessages) { SetUp(); - Logger::StringEvent("aaa", "bbb"); - Logger::StringEvent("cccc", "dddd"); - CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0)); + LOGGER->StringEvent("aaa", "bbb"); + LOGGER->StringEvent("cccc", "dddd"); + CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0)); char log_lines[100]; memset(log_lines, 0, sizeof(log_lines)); // See Logger::StringEvent. const char* line_1 = "aaa,\"bbb\"\n"; const int line_1_len = StrLength(line_1); // The exact size. - CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len)); + CHECK_EQ(line_1_len, LOGGER->GetLogLines(0, log_lines, line_1_len)); CHECK_EQ(line_1, log_lines); memset(log_lines, 0, sizeof(log_lines)); // A bit more than the first line length. - CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len + 3)); + CHECK_EQ(line_1_len, LOGGER->GetLogLines(0, log_lines, line_1_len + 3)); log_lines[line_1_len] = '\0'; CHECK_EQ(line_1, log_lines); memset(log_lines, 0, sizeof(log_lines)); const char* line_2 = "cccc,\"dddd\"\n"; const int line_2_len = StrLength(line_2); // Now start with line_2 beginning. - CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 0)); - CHECK_EQ(line_2_len, Logger::GetLogLines(line_1_len, log_lines, line_2_len)); + CHECK_EQ(0, LOGGER->GetLogLines(line_1_len, log_lines, 0)); + CHECK_EQ(line_2_len, LOGGER->GetLogLines(line_1_len, log_lines, line_2_len)); CHECK_EQ(line_2, log_lines); memset(log_lines, 0, sizeof(log_lines)); CHECK_EQ(line_2_len, - Logger::GetLogLines(line_1_len, log_lines, line_2_len + 3)); + LOGGER->GetLogLines(line_1_len, log_lines, line_2_len + 3)); CHECK_EQ(line_2, log_lines); memset(log_lines, 0, sizeof(log_lines)); // Now get entire buffer contents. const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n"; const int all_lines_len = StrLength(all_lines); - CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len)); + CHECK_EQ(all_lines_len, LOGGER->GetLogLines(0, log_lines, all_lines_len)); CHECK_EQ(all_lines, log_lines); memset(log_lines, 0, sizeof(log_lines)); - CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3)); + CHECK_EQ(all_lines_len, LOGGER->GetLogLines(0, log_lines, all_lines_len + 3)); CHECK_EQ(all_lines, log_lines); memset(log_lines, 0, sizeof(log_lines)); TearDown(); @@ -91,26 +91,26 @@ TEST(GetMessages) { static int GetLogLines(int start_pos, i::Vector<char>* buffer) { - return Logger::GetLogLines(start_pos, buffer->start(), buffer->length()); + return LOGGER->GetLogLines(start_pos, buffer->start(), buffer->length()); } TEST(BeyondWritePosition) { SetUp(); - Logger::StringEvent("aaa", "bbb"); - Logger::StringEvent("cccc", "dddd"); + LOGGER->StringEvent("aaa", "bbb"); + LOGGER->StringEvent("cccc", "dddd"); // See Logger::StringEvent. const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n"; const int all_lines_len = StrLength(all_lines); EmbeddedVector<char, 100> buffer; const int beyond_write_pos = all_lines_len; - CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos, buffer.start(), 1)); + CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos, buffer.start(), 1)); CHECK_EQ(0, GetLogLines(beyond_write_pos, &buffer)); - CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 1, buffer.start(), 1)); + CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos + 1, buffer.start(), 1)); CHECK_EQ(0, GetLogLines(beyond_write_pos + 1, &buffer)); - CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 100, buffer.start(), 1)); + CHECK_EQ(0, LOGGER->GetLogLines(beyond_write_pos + 100, buffer.start(), 1)); CHECK_EQ(0, GetLogLines(beyond_write_pos + 100, &buffer)); - CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, buffer.start(), 1)); + CHECK_EQ(0, LOGGER->GetLogLines(10 * 1024 * 1024, buffer.start(), 1)); CHECK_EQ(0, GetLogLines(10 * 1024 * 1024, &buffer)); TearDown(); } @@ -120,12 +120,12 @@ TEST(MemoryLoggingTurnedOff) { // Log to stdout i::FLAG_logfile = "-"; i::FLAG_log = true; - Logger::Setup(); - CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0)); - CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0)); - CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100)); - CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100)); - Logger::TearDown(); + LOGGER->Setup(); + CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 0)); + CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 0)); + CHECK_EQ(0, LOGGER->GetLogLines(0, NULL, 100)); + CHECK_EQ(0, LOGGER->GetLogLines(100, NULL, 100)); + LOGGER->TearDown(); } @@ -139,12 +139,12 @@ namespace internal { class LoggerTestHelper : public AllStatic { public: - static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); } + static bool IsSamplerActive() { return LOGGER->IsProfilerSamplerActive(); } static void ResetSamplesTaken() { - reinterpret_cast<Sampler*>(Logger::ticker_)->ResetSamplesTaken(); + reinterpret_cast<Sampler*>(LOGGER->ticker_)->ResetSamplesTaken(); } static bool has_samples_taken() { - return reinterpret_cast<Sampler*>(Logger::ticker_)->samples_taken() > 0; + return reinterpret_cast<Sampler*>(LOGGER->ticker_)->samples_taken() > 0; } }; @@ -166,13 +166,13 @@ class ScopedLoggerInitializer { need_to_set_up_logger_(i::V8::IsRunning()), scope_(), env_(v8::Context::New()) { - if (need_to_set_up_logger_) Logger::Setup(); + if (need_to_set_up_logger_) LOGGER->Setup(); env_->Enter(); } ~ScopedLoggerInitializer() { env_->Exit(); - Logger::TearDown(); + LOGGER->TearDown(); i::FLAG_prof_lazy = saved_prof_lazy_; i::FLAG_prof = saved_prof_; i::FLAG_prof_auto = saved_prof_auto_; @@ -251,7 +251,7 @@ static void CheckThatProfilerWorks(LogBufferMatcher* matcher) { !LoggerTestHelper::IsSamplerActive()); LoggerTestHelper::ResetSamplesTaken(); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 0); CHECK(LoggerTestHelper::IsSamplerActive()); // Verify that the current map of compiled functions has been logged. @@ -273,7 +273,7 @@ static void CheckThatProfilerWorks(LogBufferMatcher* matcher) { i::OS::Sleep(1); } - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 0); CHECK(i::RuntimeProfiler::IsEnabled() || !LoggerTestHelper::IsSamplerActive()); @@ -329,8 +329,8 @@ namespace { class LoopingThread : public v8::internal::Thread { public: - LoopingThread() - : v8::internal::Thread(), + explicit LoopingThread(v8::internal::Isolate* isolate) + : v8::internal::Thread(isolate), semaphore_(v8::internal::OS::CreateSemaphore(0)), run_(true) { } @@ -369,9 +369,12 @@ class LoopingThread : public v8::internal::Thread { class LoopingJsThread : public LoopingThread { public: + explicit LoopingJsThread(v8::internal::Isolate* isolate) + : LoopingThread(isolate) { } void RunLoop() { v8::Locker locker; - CHECK(v8::internal::ThreadManager::HasId()); + CHECK(i::Isolate::Current() != NULL); + CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0); SetV8ThreadId(); while (IsRunning()) { v8::HandleScope scope; @@ -392,11 +395,14 @@ class LoopingJsThread : public LoopingThread { class LoopingNonJsThread : public LoopingThread { public: + explicit LoopingNonJsThread(v8::internal::Isolate* isolate) + : LoopingThread(isolate) { } void RunLoop() { v8::Locker locker; v8::Unlocker unlocker; // Now thread has V8's id, but will not run VM code. - CHECK(v8::internal::ThreadManager::HasId()); + CHECK(i::Isolate::Current() != NULL); + CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0); double i = 10; SignalRunning(); while (IsRunning()) { @@ -409,8 +415,8 @@ class LoopingNonJsThread : public LoopingThread { class TestSampler : public v8::internal::Sampler { public: - TestSampler() - : Sampler(0, true, true), + explicit TestSampler(v8::internal::Isolate* isolate) + : Sampler(isolate, 0, true, true), semaphore_(v8::internal::OS::CreateSemaphore(0)), was_sample_stack_called_(false) { } @@ -441,14 +447,14 @@ TEST(ProfMultipleThreads) { TestSampler* sampler = NULL; { v8::Locker locker; - sampler = new TestSampler(); + sampler = new TestSampler(v8::internal::Isolate::Current()); sampler->Start(); CHECK(sampler->IsActive()); } - LoopingJsThread jsThread; + LoopingJsThread jsThread(v8::internal::Isolate::Current()); jsThread.Start(); - LoopingNonJsThread nonJsThread; + LoopingNonJsThread nonJsThread(v8::internal::Isolate::Current()); nonJsThread.Start(); CHECK(!sampler->WasSampleStackCalled()); @@ -515,7 +521,7 @@ TEST(Issue23768) { i_source->set_resource(NULL); // Must not crash. - i::Logger::LogCompiledFunctions(); + LOGGER->LogCompiledFunctions(); } @@ -541,7 +547,7 @@ TEST(LogCallbacks) { initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction()); CompileAndRunScript("Obj.prototype.method1.toString();"); - i::Logger::LogCompiledFunctions(); + LOGGER->LogCompiledFunctions(); CHECK_GT(matcher.GetNextChunk(), 0); const char* callback_rec = "code-creation,Callback,"; @@ -584,7 +590,7 @@ TEST(LogAccessorCallbacks) { inst->SetAccessor(v8::String::New("prop1"), Prop1Getter, Prop1Setter); inst->SetAccessor(v8::String::New("prop2"), Prop2Getter); - i::Logger::LogAccessorCallbacks(); + LOGGER->LogAccessorCallbacks(); CHECK_GT(matcher.GetNextChunk(), 0); matcher.PrintBuffer(); @@ -616,11 +622,11 @@ TEST(LogTags) { const char* close_tag = "close-tag,"; // Check compatibility with the old style behavior. - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 0); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 0); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); CHECK_EQ(NULL, matcher.Find(open_tag)); CHECK_EQ(NULL, matcher.Find(close_tag)); @@ -628,11 +634,11 @@ TEST(LogTags) { const char* close_tag1 = "close-tag,1\n"; // Check non-nested tag case. - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); CHECK_GT(matcher.GetNextChunk(), 0); CHECK(matcher.IsInSequence(open_tag1, close_tag1)); @@ -640,15 +646,15 @@ TEST(LogTags) { const char* close_tag2 = "close-tag,2\n"; // Check nested tags case. - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); CHECK_GT(matcher.GetNextChunk(), 0); // open_tag1 < open_tag2 < close_tag2 < close_tag1 CHECK(matcher.IsInSequence(open_tag1, open_tag2)); @@ -656,15 +662,15 @@ TEST(LogTags) { CHECK(matcher.IsInSequence(close_tag2, close_tag1)); // Check overlapped tags case. - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); CHECK_GT(matcher.GetNextChunk(), 0); // open_tag1 < open_tag2 < close_tag1 < close_tag2 CHECK(matcher.IsInSequence(open_tag1, open_tag2)); @@ -675,19 +681,19 @@ TEST(LogTags) { const char* close_tag3 = "close-tag,3\n"; // Check pausing overflow case. - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2); - CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 3); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 3); - CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules()); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 2); + CHECK_EQ(v8::PROFILER_MODULE_CPU, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 3); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 3); + CHECK_EQ(v8::PROFILER_MODULE_NONE, LOGGER->GetActiveProfilerModules()); // Must be no tags, because logging must be disabled. CHECK_EQ(NULL, matcher.Find(open_tag3)); CHECK_EQ(NULL, matcher.Find(close_tag3)); @@ -697,29 +703,11 @@ TEST(LogTags) { TEST(IsLoggingPreserved) { ScopedLoggerInitializer initialize_logger(false); - CHECK(Logger::is_logging()); - Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK(Logger::is_logging()); - Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1); - CHECK(Logger::is_logging()); - - CHECK(Logger::is_logging()); - Logger::ResumeProfiler( - v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1); - CHECK(Logger::is_logging()); - Logger::PauseProfiler( - v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1); - CHECK(Logger::is_logging()); - - CHECK(Logger::is_logging()); - Logger::ResumeProfiler( - v8::PROFILER_MODULE_CPU | - v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1); - CHECK(Logger::is_logging()); - Logger::PauseProfiler( - v8::PROFILER_MODULE_CPU | - v8::PROFILER_MODULE_HEAP_STATS | v8::PROFILER_MODULE_JS_CONSTRUCTORS, 1); - CHECK(Logger::is_logging()); + CHECK(LOGGER->is_logging()); + LOGGER->ResumeProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK(LOGGER->is_logging()); + LOGGER->PauseProfiler(v8::PROFILER_MODULE_CPU, 1); + CHECK(LOGGER->is_logging()); } @@ -1128,7 +1116,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { " obj.test =\n" " (function a(j) { return function b() { return j; } })(100);\n" "})(this);"); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); EmbeddedVector<char, 204800> buffer; int log_size; @@ -1148,9 +1136,9 @@ TEST(EquivalenceOfLoggingAndTraversal) { } // Iterate heap to find compiled functions, will write to log. - i::Logger::LogCompiledFunctions(); + LOGGER->LogCompiledFunctions(); char* new_log_start = buffer.start() + log_size; - const int new_log_size = Logger::GetLogLines( + const int new_log_size = LOGGER->GetLogLines( log_size, new_log_start, buffer.length() - log_size); CHECK_GT(new_log_size, 0); CHECK_GT(buffer.length(), log_size + new_log_size); @@ -1184,7 +1172,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { CHECK(results_equal); env->Exit(); - Logger::TearDown(); + LOGGER->TearDown(); i::FLAG_always_compact = saved_always_compact; } diff --git a/deps/v8/test/cctest/test-macro-assembler-x64.cc b/deps/v8/test/cctest/test-macro-assembler-x64.cc index 9b1fc46ea..59eeed906 100755 --- a/deps/v8/test/cctest/test-macro-assembler-x64.cc +++ b/deps/v8/test/cctest/test-macro-assembler-x64.cc @@ -35,48 +35,49 @@ #include "serialize.h" #include "cctest.h" -using v8::internal::byte; -using v8::internal::OS; using v8::internal::Assembler; +using v8::internal::CodeDesc; using v8::internal::Condition; -using v8::internal::MacroAssembler; +using v8::internal::FUNCTION_CAST; using v8::internal::HandleScope; -using v8::internal::Operand; using v8::internal::Immediate; -using v8::internal::SmiIndex; +using v8::internal::Isolate; using v8::internal::Label; +using v8::internal::MacroAssembler; +using v8::internal::OS; +using v8::internal::Operand; using v8::internal::RelocInfo; +using v8::internal::Smi; +using v8::internal::SmiIndex; +using v8::internal::byte; +using v8::internal::carry; +using v8::internal::greater; +using v8::internal::greater_equal; +using v8::internal::kIntSize; +using v8::internal::kPointerSize; +using v8::internal::kSmiTagMask; +using v8::internal::kSmiValueSize; +using v8::internal::less_equal; +using v8::internal::negative; +using v8::internal::not_carry; +using v8::internal::not_equal; +using v8::internal::not_zero; +using v8::internal::positive; +using v8::internal::r11; +using v8::internal::r13; +using v8::internal::r14; +using v8::internal::r15; +using v8::internal::r8; +using v8::internal::r9; using v8::internal::rax; +using v8::internal::rbp; using v8::internal::rbx; -using v8::internal::rsi; -using v8::internal::rdi; using v8::internal::rcx; +using v8::internal::rdi; using v8::internal::rdx; -using v8::internal::rbp; +using v8::internal::rsi; using v8::internal::rsp; -using v8::internal::r8; -using v8::internal::r9; -using v8::internal::r11; -using v8::internal::r12; -using v8::internal::r13; -using v8::internal::r14; using v8::internal::times_pointer_size; -using v8::internal::FUNCTION_CAST; -using v8::internal::CodeDesc; -using v8::internal::less_equal; -using v8::internal::not_equal; -using v8::internal::not_zero; -using v8::internal::greater; -using v8::internal::greater_equal; -using v8::internal::carry; -using v8::internal::not_carry; -using v8::internal::negative; -using v8::internal::positive; -using v8::internal::Smi; -using v8::internal::kSmiTagMask; -using v8::internal::kSmiValueSize; -using v8::internal::kPointerSize; -using v8::internal::kIntSize; // Test the x64 assembler by compiling some simple functions into // a buffer and executing them. These tests do not initialize the @@ -95,7 +96,9 @@ typedef int (*F0)(); static void EntryCode(MacroAssembler* masm) { // Smi constant register is callee save. __ push(v8::internal::kSmiConstantRegister); + __ push(v8::internal::kRootRegister); __ InitializeSmiConstantRegister(); + __ InitializeRootRegister(); } @@ -105,6 +108,7 @@ static void ExitCode(MacroAssembler* masm) { __ cmpq(rdx, v8::internal::kSmiConstantRegister); __ movq(rdx, Immediate(-1)); __ cmovq(not_equal, rax, rdx); + __ pop(v8::internal::kRootRegister); __ pop(v8::internal::kSmiConstantRegister); } @@ -146,6 +150,7 @@ static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) { // Test that we can move a Smi value literally into a register. TEST(SmiMove) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -153,7 +158,9 @@ TEST(SmiMove) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. masm->set_allow_stub_calls(false); EntryCode(masm); @@ -220,7 +227,7 @@ void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ j(less_equal, exit); } } else { - __ SmiCompare(rcx, rcx); + __ cmpq(rcx, rcx); __ movl(rax, Immediate(id + 11)); __ j(not_equal, exit); __ incq(rax); @@ -232,15 +239,18 @@ void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) { // Test that we can compare smis for equality (and more). TEST(SmiCompare) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = - static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, + static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2, &actual_size, true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -282,6 +292,7 @@ TEST(SmiCompare) { TEST(Integer32ToSmi) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -289,7 +300,9 @@ TEST(Integer32ToSmi) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -300,35 +313,35 @@ TEST(Integer32ToSmi) { __ movl(rcx, Immediate(0)); __ Integer32ToSmi(rcx, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0))); - __ SmiCompare(rcx, rdx); + __ cmpq(rcx, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(2)); // Test number. __ movl(rcx, Immediate(1024)); __ Integer32ToSmi(rcx, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024))); - __ SmiCompare(rcx, rdx); + __ cmpq(rcx, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(3)); // Test number. __ movl(rcx, Immediate(-1)); __ Integer32ToSmi(rcx, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1))); - __ SmiCompare(rcx, rdx); + __ cmpq(rcx, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(4)); // Test number. __ movl(rcx, Immediate(Smi::kMaxValue)); __ Integer32ToSmi(rcx, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue))); - __ SmiCompare(rcx, rdx); + __ cmpq(rcx, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(5)); // Test number. __ movl(rcx, Immediate(Smi::kMinValue)); __ Integer32ToSmi(rcx, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue))); - __ SmiCompare(rcx, rdx); + __ cmpq(rcx, rdx); __ j(not_equal, &exit); // Different target register. @@ -337,35 +350,35 @@ TEST(Integer32ToSmi) { __ movl(rcx, Immediate(0)); __ Integer32ToSmi(r8, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0))); - __ SmiCompare(r8, rdx); + __ cmpq(r8, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(7)); // Test number. __ movl(rcx, Immediate(1024)); __ Integer32ToSmi(r8, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024))); - __ SmiCompare(r8, rdx); + __ cmpq(r8, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(8)); // Test number. __ movl(rcx, Immediate(-1)); __ Integer32ToSmi(r8, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1))); - __ SmiCompare(r8, rdx); + __ cmpq(r8, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(9)); // Test number. __ movl(rcx, Immediate(Smi::kMaxValue)); __ Integer32ToSmi(r8, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue))); - __ SmiCompare(r8, rdx); + __ cmpq(r8, rdx); __ j(not_equal, &exit); __ movq(rax, Immediate(10)); // Test number. __ movl(rcx, Immediate(Smi::kMinValue)); __ Integer32ToSmi(r8, rcx); __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue))); - __ SmiCompare(r8, rdx); + __ cmpq(r8, rdx); __ j(not_equal, &exit); @@ -394,21 +407,22 @@ void TestI64PlusConstantToSmi(MacroAssembler* masm, __ movq(rcx, x, RelocInfo::NONE); __ movq(r11, rcx); __ Integer64PlusConstantToSmi(rdx, rcx, y); - __ SmiCompare(rdx, r8); + __ cmpq(rdx, r8); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ Integer64PlusConstantToSmi(rcx, rcx, y); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } TEST(Integer64PlusConstantToSmi) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -416,7 +430,9 @@ TEST(Integer64PlusConstantToSmi) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -452,6 +468,7 @@ TEST(Integer64PlusConstantToSmi) { TEST(SmiCheck) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -459,7 +476,9 @@ TEST(SmiCheck) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -660,14 +679,14 @@ void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiNeg(r9, rcx, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiNeg(rcx, rcx, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); } else { Label smi_ok, smi_ok2; @@ -679,11 +698,11 @@ void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) { __ jmp(exit); __ bind(&smi_ok); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); @@ -691,13 +710,14 @@ void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) { __ jmp(exit); __ bind(&smi_ok2); __ incq(rax); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } } TEST(SmiNeg) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -706,7 +726,9 @@ TEST(SmiNeg) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -751,12 +773,12 @@ static void SmiAddTest(MacroAssembler* masm, __ movl(rax, Immediate(id)); // Test number. __ SmiAdd(r9, rcx, rdx, exit); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); __ SmiAdd(rcx, rcx, rdx, exit); \ - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ movl(rcx, Immediate(first)); @@ -764,11 +786,11 @@ static void SmiAddTest(MacroAssembler* masm, __ incq(rax); __ SmiAddConstant(r9, rcx, Smi::FromInt(second)); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ SmiAddConstant(rcx, rcx, Smi::FromInt(second)); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ movl(rcx, Immediate(first)); @@ -776,16 +798,17 @@ static void SmiAddTest(MacroAssembler* masm, __ incq(rax); __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } TEST(SmiAdd) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -793,7 +816,9 @@ TEST(SmiAdd) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -834,36 +859,36 @@ static void SmiSubTest(MacroAssembler* masm, __ movl(rax, Immediate(id)); // Test 0. __ SmiSub(r9, rcx, rdx, exit); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); // Test 1. __ SmiSub(rcx, rcx, rdx, exit); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ Move(rcx, Smi::FromInt(first)); __ incq(rax); // Test 2. __ SmiSubConstant(r9, rcx, Smi::FromInt(second)); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); // Test 3. __ SmiSubConstant(rcx, rcx, Smi::FromInt(second)); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ Move(rcx, Smi::FromInt(first)); __ incq(rax); // Test 4. __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); // Test 5. __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } @@ -886,7 +911,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -897,7 +922,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -909,7 +934,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -920,7 +945,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -933,7 +958,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -944,7 +969,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -956,7 +981,7 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } @@ -967,13 +992,14 @@ static void SmiSubOverflowTest(MacroAssembler* masm, __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); } } TEST(SmiSub) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -982,7 +1008,9 @@ TEST(SmiSub) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1032,15 +1060,15 @@ void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ Move(r8, Smi::FromIntptr(result)); __ SmiMul(r9, rcx, rdx, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); __ SmiMul(rcx, rcx, rdx, exit); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } else { __ movl(rax, Immediate(id + 8)); @@ -1049,7 +1077,7 @@ void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ jmp(exit); __ bind(&overflow_ok); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiMul(rcx, rcx, rdx, &overflow_ok2); @@ -1057,13 +1085,14 @@ void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ bind(&overflow_ok2); // 31-bit version doesn't preserve rcx on failure. // __ incq(rax); - // __ SmiCompare(r11, rcx); + // __ cmpq(r11, rcx); // __ j(not_equal, exit); } } TEST(SmiMul) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -1071,7 +1100,9 @@ TEST(SmiMul) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1120,30 +1151,30 @@ void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) { if (!fraction && !overflow && !negative_zero && !division_by_zero) { // Division succeeds __ movq(rcx, r11); - __ movq(r12, Immediate(id)); + __ movq(r15, Immediate(id)); int result = x / y; __ Move(r8, Smi::FromInt(result)); __ SmiDiv(r9, rcx, r14, exit); // Might have destroyed rcx and r14. - __ incq(r12); - __ SmiCompare(r9, r8); + __ incq(r15); + __ cmpq(r9, r8); __ j(not_equal, exit); - __ incq(r12); + __ incq(r15); __ movq(rcx, r11); __ Move(r14, Smi::FromInt(y)); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); - __ incq(r12); + __ incq(r15); __ SmiDiv(rcx, rcx, r14, exit); - __ incq(r12); - __ SmiCompare(rcx, r8); + __ incq(r15); + __ cmpq(rcx, r8); __ j(not_equal, exit); } else { // Division fails. - __ movq(r12, Immediate(id + 8)); + __ movq(r15, Immediate(id + 8)); Label fail_ok, fail_ok2; __ movq(rcx, r11); @@ -1151,23 +1182,24 @@ void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ jmp(exit); __ bind(&fail_ok); - __ incq(r12); - __ SmiCompare(rcx, r11); + __ incq(r15); + __ cmpq(rcx, r11); __ j(not_equal, exit); - __ incq(r12); + __ incq(r15); __ SmiDiv(rcx, rcx, r14, &fail_ok2); __ jmp(exit); __ bind(&fail_ok2); - __ incq(r12); - __ SmiCompare(rcx, r11); + __ incq(r15); + __ cmpq(rcx, r11); __ j(not_equal, exit); } } TEST(SmiDiv) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1176,7 +1208,9 @@ TEST(SmiDiv) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1184,7 +1218,7 @@ TEST(SmiDiv) { Label exit; __ push(r14); - __ push(r12); + __ push(r15); TestSmiDiv(masm, &exit, 0x10, 1, 1); TestSmiDiv(masm, &exit, 0x20, 1, 0); TestSmiDiv(masm, &exit, 0x30, -1, 0); @@ -1206,10 +1240,10 @@ TEST(SmiDiv) { TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue); TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1); - __ xor_(r12, r12); // Success. + __ xor_(r15, r15); // Success. __ bind(&exit); - __ movq(rax, r12); - __ pop(r12); + __ movq(rax, r15); + __ pop(r15); __ pop(r14); ExitCode(masm); __ ret(0); @@ -1232,51 +1266,52 @@ void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ Move(r14, Smi::FromInt(y)); if (!division_overflow && !negative_zero && !division_by_zero) { // Modulo succeeds - __ movq(r12, Immediate(id)); + __ movq(r15, Immediate(id)); int result = x % y; __ Move(r8, Smi::FromInt(result)); __ SmiMod(r9, rcx, r14, exit); - __ incq(r12); - __ SmiCompare(r9, r8); + __ incq(r15); + __ cmpq(r9, r8); __ j(not_equal, exit); - __ incq(r12); - __ SmiCompare(rcx, r11); + __ incq(r15); + __ cmpq(rcx, r11); __ j(not_equal, exit); - __ incq(r12); + __ incq(r15); __ SmiMod(rcx, rcx, r14, exit); - __ incq(r12); - __ SmiCompare(rcx, r8); + __ incq(r15); + __ cmpq(rcx, r8); __ j(not_equal, exit); } else { // Modulo fails. - __ movq(r12, Immediate(id + 8)); + __ movq(r15, Immediate(id + 8)); Label fail_ok, fail_ok2; __ SmiMod(r9, rcx, r14, &fail_ok); __ jmp(exit); __ bind(&fail_ok); - __ incq(r12); - __ SmiCompare(rcx, r11); + __ incq(r15); + __ cmpq(rcx, r11); __ j(not_equal, exit); - __ incq(r12); + __ incq(r15); __ SmiMod(rcx, rcx, r14, &fail_ok2); __ jmp(exit); __ bind(&fail_ok2); - __ incq(r12); - __ SmiCompare(rcx, r11); + __ incq(r15); + __ cmpq(rcx, r11); __ j(not_equal, exit); } } TEST(SmiMod) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1285,7 +1320,9 @@ TEST(SmiMod) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1293,7 +1330,7 @@ TEST(SmiMod) { Label exit; __ push(r14); - __ push(r12); + __ push(r15); TestSmiMod(masm, &exit, 0x10, 1, 1); TestSmiMod(masm, &exit, 0x20, 1, 0); TestSmiMod(masm, &exit, 0x30, -1, 0); @@ -1315,10 +1352,10 @@ TEST(SmiMod) { TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue); TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1); - __ xor_(r12, r12); // Success. + __ xor_(r15, r15); // Success. __ bind(&exit); - __ movq(rax, r12); - __ pop(r12); + __ movq(rax, r15); + __ pop(r15); __ pop(r14); ExitCode(masm); __ ret(0); @@ -1340,7 +1377,7 @@ void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) { ASSERT(index.reg.is(rcx) || index.reg.is(rdx)); __ shl(index.reg, Immediate(index.scale)); __ Set(r8, static_cast<intptr_t>(x) << i); - __ SmiCompare(index.reg, r8); + __ cmpq(index.reg, r8); __ j(not_equal, exit); __ incq(rax); __ Move(rcx, Smi::FromInt(x)); @@ -1348,7 +1385,7 @@ void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) { ASSERT(index.reg.is(rcx)); __ shl(rcx, Immediate(index.scale)); __ Set(r8, static_cast<intptr_t>(x) << i); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ incq(rax); @@ -1357,7 +1394,7 @@ void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) { ASSERT(index.reg.is(rcx) || index.reg.is(rdx)); __ shl(index.reg, Immediate(index.scale)); __ Set(r8, static_cast<intptr_t>(-x) << i); - __ SmiCompare(index.reg, r8); + __ cmpq(index.reg, r8); __ j(not_equal, exit); __ incq(rax); __ Move(rcx, Smi::FromInt(x)); @@ -1365,13 +1402,14 @@ void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) { ASSERT(index.reg.is(rcx)); __ shl(rcx, Immediate(index.scale)); __ Set(r8, static_cast<intptr_t>(-x) << i); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ incq(rax); } } TEST(SmiIndex) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1380,7 +1418,9 @@ TEST(SmiIndex) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1414,7 +1454,7 @@ void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ SelectNonSmi(r9, rcx, rdx, exit); __ incq(rax); - __ SmiCompare(r9, rdx); + __ cmpq(r9, rdx); __ j(not_equal, exit); __ incq(rax); @@ -1424,7 +1464,7 @@ void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ SelectNonSmi(r9, rcx, rdx, exit); __ incq(rax); - __ SmiCompare(r9, rcx); + __ cmpq(r9, rcx); __ j(not_equal, exit); __ incq(rax); @@ -1440,6 +1480,7 @@ void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) { TEST(SmiSelectNonSmi) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1448,7 +1489,9 @@ TEST(SmiSelectNonSmi) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); // Avoid inline checks. @@ -1488,36 +1531,37 @@ void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ Move(rdx, Smi::FromInt(y)); __ Move(r8, Smi::FromInt(result)); __ SmiAnd(r9, rcx, rdx); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiAnd(rcx, rcx, rdx); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); __ movq(rcx, r11); __ incq(rax); __ SmiAndConstant(r9, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiAndConstant(rcx, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); } TEST(SmiAnd) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1526,7 +1570,9 @@ TEST(SmiAnd) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1568,36 +1614,37 @@ void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ Move(rdx, Smi::FromInt(y)); __ Move(r8, Smi::FromInt(result)); __ SmiOr(r9, rcx, rdx); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiOr(rcx, rcx, rdx); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); __ movq(rcx, r11); __ incq(rax); __ SmiOrConstant(r9, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiOrConstant(rcx, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); } TEST(SmiOr) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1606,7 +1653,9 @@ TEST(SmiOr) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1650,36 +1699,37 @@ void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) { __ Move(rdx, Smi::FromInt(y)); __ Move(r8, Smi::FromInt(result)); __ SmiXor(r9, rcx, rdx); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiXor(rcx, rcx, rdx); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); __ movq(rcx, r11); __ incq(rax); __ SmiXorConstant(r9, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, r9); + __ cmpq(r8, r9); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiXorConstant(rcx, rcx, Smi::FromInt(y)); - __ SmiCompare(r8, rcx); + __ cmpq(r8, rcx); __ j(not_equal, exit); } TEST(SmiXor) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1688,7 +1738,9 @@ TEST(SmiXor) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1731,21 +1783,22 @@ void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) { __ movq(r11, rcx); __ SmiNot(r9, rcx); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); + __ cmpq(r11, rcx); __ j(not_equal, exit); __ incq(rax); __ SmiNot(rcx, rcx); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); } TEST(SmiNot) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1754,7 +1807,9 @@ TEST(SmiNot) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1797,7 +1852,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiShiftLeftConstant(r9, rcx, shift); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1805,7 +1860,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiShiftLeftConstant(rcx, rcx, shift); __ incq(rax); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ incq(rax); @@ -1814,7 +1869,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiShiftLeft(r9, rdx, rcx); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1823,7 +1878,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiShiftLeft(r9, rdx, r11); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1832,7 +1887,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { __ SmiShiftLeft(rdx, rdx, r11); __ incq(rax); - __ SmiCompare(rdx, r8); + __ cmpq(rdx, r8); __ j(not_equal, exit); __ incq(rax); @@ -1841,6 +1896,7 @@ void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) { TEST(SmiShiftLeft) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1849,7 +1905,9 @@ TEST(SmiShiftLeft) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1893,7 +1951,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1902,7 +1960,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, __ SmiShiftLogicalRight(r9, rdx, rcx, exit); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1911,7 +1969,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, __ SmiShiftLogicalRight(r9, rdx, r11, exit); __ incq(rax); - __ SmiCompare(r9, r8); + __ cmpq(r9, r8); __ j(not_equal, exit); __ incq(rax); @@ -1925,7 +1983,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, __ bind(&fail_ok); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); __ incq(rax); @@ -1936,7 +1994,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, __ bind(&fail_ok3); __ incq(rax); - __ SmiCompare(rcx, r11); + __ cmpq(rcx, r11); __ j(not_equal, exit); __ addq(rax, Immediate(3)); @@ -1946,6 +2004,7 @@ void TestSmiShiftLogicalRight(MacroAssembler* masm, TEST(SmiShiftLogicalRight) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -1954,7 +2013,9 @@ TEST(SmiShiftLogicalRight) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -1997,7 +2058,7 @@ void TestSmiShiftArithmeticRight(MacroAssembler* masm, __ Move(rcx, Smi::FromInt(x)); __ SmiShiftArithmeticRightConstant(rcx, rcx, shift); - __ SmiCompare(rcx, r8); + __ cmpq(rcx, r8); __ j(not_equal, exit); __ incq(rax); @@ -2005,7 +2066,7 @@ void TestSmiShiftArithmeticRight(MacroAssembler* masm, __ Move(r11, Smi::FromInt(shift)); __ SmiShiftArithmeticRight(rdx, rdx, r11); - __ SmiCompare(rdx, r8); + __ cmpq(rdx, r8); __ j(not_equal, exit); __ incq(rax); @@ -2014,6 +2075,7 @@ void TestSmiShiftArithmeticRight(MacroAssembler* masm, TEST(SmiShiftArithmeticRight) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = @@ -2022,7 +2084,9 @@ TEST(SmiShiftArithmeticRight) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -2062,14 +2126,14 @@ void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) { __ Move(rcx, Smi::FromInt(x)); __ movq(r11, rcx); __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power); - __ SmiCompare(rdx, r8); + __ cmpq(rdx, r8); __ j(not_equal, exit); __ incq(rax); - __ SmiCompare(r11, rcx); // rcx unchanged. + __ cmpq(r11, rcx); // rcx unchanged. __ j(not_equal, exit); __ incq(rax); __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power); - __ SmiCompare(rdx, r8); + __ cmpq(rdx, r8); __ j(not_equal, exit); __ incq(rax); } @@ -2077,15 +2141,18 @@ void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) { TEST(PositiveSmiTimesPowerOfTwoToInteger64) { + v8::internal::V8::Initialize(NULL); // Allocate an executable page of memory. size_t actual_size; byte* buffer = - static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2, + static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4, &actual_size, true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -2116,6 +2183,7 @@ TEST(PositiveSmiTimesPowerOfTwoToInteger64) { TEST(OperandOffset) { + v8::internal::V8::Initialize(NULL); int data[256]; for (int i = 0; i < 256; i++) { data[i] = i * 0x01010101; } @@ -2127,7 +2195,9 @@ TEST(OperandOffset) { true)); CHECK(buffer); HandleScope handles; - MacroAssembler assembler(buffer, static_cast<int>(actual_size)); + MacroAssembler assembler(Isolate::Current(), + buffer, + static_cast<int>(actual_size)); MacroAssembler* masm = &assembler; masm->set_allow_stub_calls(false); @@ -2150,7 +2220,7 @@ TEST(OperandOffset) { __ push(Immediate(0x108)); __ push(Immediate(0x109)); // <-- rsp // rbp = rsp[9] - // r12 = rsp[3] + // r15 = rsp[3] // rbx = rsp[5] // r13 = rsp[7] __ lea(r14, Operand(rsp, 3 * kPointerSize)); diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc index 3e3175e73..dcb51a0bc 100644 --- a/deps/v8/test/cctest/test-mark-compact.cc +++ b/deps/v8/test/cctest/test-mark-compact.cc @@ -31,7 +31,6 @@ #include "global-handles.h" #include "snapshot.h" -#include "top.h" #include "cctest.h" using namespace v8::internal; @@ -79,7 +78,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, 4*MB, 4*MB); InitializeVM(); @@ -87,25 +86,25 @@ TEST(Promotion) { // Allocate a fixed array in the new space. int array_size = - (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / + (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / (kPointerSize * 4); - Object* obj = Heap::AllocateFixedArray(array_size)->ToObjectChecked(); + Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); // Array should be in the new space. - CHECK(Heap::InSpace(*array, NEW_SPACE)); + CHECK(HEAP->InSpace(*array, NEW_SPACE)); // Call the m-c collector, so array becomes an old object. - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // Array now sits in the old space - CHECK(Heap::InSpace(*array, OLD_POINTER_SPACE)); + CHECK(HEAP->InSpace(*array, OLD_POINTER_SPACE)); } TEST(NoPromotion) { - Heap::ConfigureHeap(2*256*KB, 4*MB, 4*MB); + HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB); // Test the situation that some objects in new space are promoted to // the old space @@ -114,23 +113,23 @@ TEST(NoPromotion) { v8::HandleScope sc; // Do a mark compact GC to shrink the heap. - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // Allocate a big Fixed array in the new space. - int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / + int size = (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / kPointerSize; - Object* obj = Heap::AllocateFixedArray(size)->ToObjectChecked(); + Object* obj = HEAP->AllocateFixedArray(size)->ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); // Array still stays in the new space. - CHECK(Heap::InSpace(*array, NEW_SPACE)); + CHECK(HEAP->InSpace(*array, NEW_SPACE)); // Allocate objects in the old space until out of memory. FixedArray* host = *array; while (true) { Object* obj; - { MaybeObject* maybe_obj = Heap::AllocateFixedArray(100, TENURED); + { MaybeObject* maybe_obj = HEAP->AllocateFixedArray(100, TENURED); if (!maybe_obj->ToObject(&obj)) break; } @@ -139,10 +138,10 @@ TEST(NoPromotion) { } // Call mark compact GC, and it should pass. - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // array should not be promoted because the old space is full. - CHECK(Heap::InSpace(*array, NEW_SPACE)); + CHECK(HEAP->InSpace(*array, NEW_SPACE)); } @@ -151,90 +150,86 @@ TEST(MarkCompactCollector) { v8::HandleScope sc; // call mark-compact when heap is empty - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // keep allocating garbage in new space until it fails const int ARRAY_SIZE = 100; Object* array; MaybeObject* maybe_array; do { - maybe_array = Heap::AllocateFixedArray(ARRAY_SIZE); + maybe_array = HEAP->AllocateFixedArray(ARRAY_SIZE); } while (maybe_array->ToObject(&array)); - Heap::CollectGarbage(NEW_SPACE); + HEAP->CollectGarbage(NEW_SPACE); - array = Heap::AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked(); + array = HEAP->AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked(); // keep allocating maps until it fails Object* mapp; MaybeObject* maybe_mapp; do { - maybe_mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + maybe_mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); } while (maybe_mapp->ToObject(&mapp)); - Heap::CollectGarbage(MAP_SPACE); - mapp = Heap::AllocateMap(JS_OBJECT_TYPE, + HEAP->CollectGarbage(MAP_SPACE); + mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)->ToObjectChecked(); // allocate a garbage String* func_name = - String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked()); + String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked()); SharedFunctionInfo* function_share = SharedFunctionInfo::cast( - Heap::AllocateSharedFunctionInfo(func_name)->ToObjectChecked()); + HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked()); JSFunction* function = JSFunction::cast( - Heap::AllocateFunction(*Top::function_map(), + HEAP->AllocateFunction(*Isolate::Current()->function_map(), function_share, - Heap::undefined_value())->ToObjectChecked()); + HEAP->undefined_value())->ToObjectChecked()); Map* initial_map = - Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, + Map::cast(HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)->ToObjectChecked()); function->set_initial_map(initial_map); - Top::context()->global()->SetProperty(func_name, - function, - NONE, - kNonStrictMode)->ToObjectChecked(); + Isolate::Current()->context()->global()->SetProperty( + func_name, function, NONE, kNonStrictMode)->ToObjectChecked(); - JSObject* obj = - JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked()); - Heap::CollectGarbage(OLD_POINTER_SPACE); + JSObject* obj = JSObject::cast( + HEAP->AllocateJSObject(function)->ToObjectChecked()); + HEAP->CollectGarbage(OLD_POINTER_SPACE); func_name = - String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked()); - CHECK(Top::context()->global()->HasLocalProperty(func_name)); - Object* func_value = - Top::context()->global()->GetProperty(func_name)->ToObjectChecked(); + String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked()); + CHECK(Isolate::Current()->context()->global()->HasLocalProperty(func_name)); + Object* func_value = Isolate::Current()->context()->global()-> + GetProperty(func_name)->ToObjectChecked(); CHECK(func_value->IsJSFunction()); function = JSFunction::cast(func_value); - obj = JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked()); + obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked()); String* obj_name = - String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked()); - Top::context()->global()->SetProperty(obj_name, - obj, - NONE, - kNonStrictMode)->ToObjectChecked(); + String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked()); + Isolate::Current()->context()->global()->SetProperty( + obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked(); String* prop_name = - String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked()); + String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked()); obj->SetProperty(prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); obj_name = - String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked()); - CHECK(Top::context()->global()->HasLocalProperty(obj_name)); - CHECK(Top::context()->global()-> - GetProperty(obj_name)->ToObjectChecked()->IsJSObject()); - obj = JSObject::cast( - Top::context()->global()->GetProperty(obj_name)->ToObjectChecked()); + String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked()); + CHECK(Isolate::Current()->context()->global()->HasLocalProperty(obj_name)); + CHECK(Isolate::Current()->context()->global()-> + GetProperty(obj_name)->ToObjectChecked()->IsJSObject()); + obj = JSObject::cast(Isolate::Current()->context()->global()-> + GetProperty(obj_name)->ToObjectChecked()); prop_name = - String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked()); - CHECK(obj->GetProperty(prop_name)->ToObjectChecked() == Smi::FromInt(23)); + String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked()); + CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23)); } static Handle<Map> CreateMap() { - return Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); } @@ -246,20 +241,20 @@ TEST(MapCompact) { v8::HandleScope sc; // keep allocating maps while pointers are still encodable and thus // mark compact is permitted. - Handle<JSObject> root = Factory::NewJSObjectFromMap(CreateMap()); + Handle<JSObject> root = FACTORY->NewJSObjectFromMap(CreateMap()); do { Handle<Map> map = CreateMap(); map->set_prototype(*root); - root = Factory::NewJSObjectFromMap(map); - } while (Heap::map_space()->MapPointersEncodable()); + root = FACTORY->NewJSObjectFromMap(map); + } while (HEAP->map_space()->MapPointersEncodable()); } // Now, as we don't have any handles to just allocated maps, we should // 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(true); // And now map pointers should be encodable again. - CHECK(Heap::map_space()->MapPointersEncodable()); + CHECK(HEAP->map_space()->MapPointersEncodable()); } @@ -281,16 +276,16 @@ static void GCEpilogueCallbackFunc() { TEST(GCCallback) { InitializeVM(); - Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc); - Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc); + HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc); + HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc); // Scavenge does not call GC callback functions. - Heap::PerformScavenge(); + HEAP->PerformScavenge(); CHECK_EQ(0, gc_starts); CHECK_EQ(gc_ends, gc_starts); - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); CHECK_EQ(1, gc_starts); CHECK_EQ(gc_ends, gc_starts); } @@ -298,39 +293,51 @@ TEST(GCCallback) { static int NumberOfWeakCalls = 0; static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) { + ASSERT(id == reinterpret_cast<void*>(1234)); NumberOfWeakCalls++; handle.Dispose(); } TEST(ObjectGroups) { InitializeVM(); + GlobalHandles* global_handles = Isolate::Current()->global_handles(); NumberOfWeakCalls = 0; v8::HandleScope handle_scope; Handle<Object> g1s1 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); Handle<Object> g1s2 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); - GlobalHandles::MakeWeak(g1s1.location(), - reinterpret_cast<void*>(1234), - &WeakPointerCallback); - GlobalHandles::MakeWeak(g1s2.location(), - reinterpret_cast<void*>(1234), - &WeakPointerCallback); + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); + Handle<Object> g1c1 = + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); + global_handles->MakeWeak(g1s1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + global_handles->MakeWeak(g1s2.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + global_handles->MakeWeak(g1c1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); Handle<Object> g2s1 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); Handle<Object> g2s2 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); - GlobalHandles::MakeWeak(g2s1.location(), - reinterpret_cast<void*>(1234), - &WeakPointerCallback); - GlobalHandles::MakeWeak(g2s2.location(), - reinterpret_cast<void*>(1234), - &WeakPointerCallback); - - Handle<Object> root = GlobalHandles::Create(*g1s1); // make a root. + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); + Handle<Object> g2c1 = + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); + global_handles->MakeWeak(g2s1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + global_handles->MakeWeak(g2s2.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + global_handles->MakeWeak(g2c1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + + Handle<Object> root = global_handles->Create(*g1s1); // make a root. // Connect group 1 and 2, make a cycle. Handle<FixedArray>::cast(g1s2)->set(0, *g2s2); @@ -338,31 +345,100 @@ TEST(ObjectGroups) { { Object** g1_objects[] = { g1s1.location(), g1s2.location() }; + Object** g1_children[] = { g1c1.location() }; Object** g2_objects[] = { g2s1.location(), g2s2.location() }; - GlobalHandles::AddGroup(g1_objects, 2); - GlobalHandles::AddGroup(g2_objects, 2); + Object** g2_children[] = { g2c1.location() }; + global_handles->AddObjectGroup(g1_objects, 2, NULL); + global_handles->AddImplicitReferences( + Handle<HeapObject>::cast(g1s1).location(), g1_children, 1); + global_handles->AddObjectGroup(g2_objects, 2, NULL); + global_handles->AddImplicitReferences( + Handle<HeapObject>::cast(g2s2).location(), g2_children, 1); } // Do a full GC - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // All object should be alive. CHECK_EQ(0, NumberOfWeakCalls); // Weaken the root. - GlobalHandles::MakeWeak(root.location(), - reinterpret_cast<void*>(1234), - &WeakPointerCallback); + global_handles->MakeWeak(root.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + // But make children strong roots---all the objects (except for children) + // should be collectable now. + global_handles->ClearWeakness(g1c1.location()); + global_handles->ClearWeakness(g2c1.location()); // Groups are deleted, rebuild groups. { Object** g1_objects[] = { g1s1.location(), g1s2.location() }; + Object** g1_children[] = { g1c1.location() }; Object** g2_objects[] = { g2s1.location(), g2s2.location() }; - GlobalHandles::AddGroup(g1_objects, 2); - GlobalHandles::AddGroup(g2_objects, 2); + Object** g2_children[] = { g2c1.location() }; + global_handles->AddObjectGroup(g1_objects, 2, NULL); + global_handles->AddImplicitReferences( + Handle<HeapObject>::cast(g1s1).location(), g1_children, 1); + global_handles->AddObjectGroup(g2_objects, 2, NULL); + global_handles->AddImplicitReferences( + Handle<HeapObject>::cast(g2s2).location(), g2_children, 1); } - Heap::CollectGarbage(OLD_POINTER_SPACE); + HEAP->CollectGarbage(OLD_POINTER_SPACE); // All objects should be gone. 5 global handles in total. CHECK_EQ(5, NumberOfWeakCalls); + + // And now make children weak again and collect them. + global_handles->MakeWeak(g1c1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + global_handles->MakeWeak(g2c1.location(), + reinterpret_cast<void*>(1234), + &WeakPointerCallback); + + HEAP->CollectGarbage(OLD_POINTER_SPACE); + CHECK_EQ(7, NumberOfWeakCalls); +} + + +class TestRetainedObjectInfo : public v8::RetainedObjectInfo { + public: + TestRetainedObjectInfo() : has_been_disposed_(false) {} + + bool has_been_disposed() { return has_been_disposed_; } + + virtual void Dispose() { + ASSERT(!has_been_disposed_); + has_been_disposed_ = true; + } + + virtual bool IsEquivalent(v8::RetainedObjectInfo* other) { + return other == this; + } + + virtual intptr_t GetHash() { return 0; } + + virtual const char* GetLabel() { return "whatever"; } + + private: + bool has_been_disposed_; +}; + + +TEST(EmptyObjectGroups) { + InitializeVM(); + GlobalHandles* global_handles = Isolate::Current()->global_handles(); + + v8::HandleScope handle_scope; + + Handle<Object> object = + global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked()); + + TestRetainedObjectInfo info; + global_handles->AddObjectGroup(NULL, 0, &info); + ASSERT(info.has_been_disposed()); + + global_handles->AddImplicitReferences( + Handle<HeapObject>::cast(object).location(), NULL, 0); } diff --git a/deps/v8/test/cctest/test-mips.cc b/deps/v8/test/cctest/test-mips.cc deleted file mode 100644 index efd4cc975..000000000 --- a/deps/v8/test/cctest/test-mips.cc +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - - -#include "v8.h" -#include "execution.h" - -#include "cctest.h" - -using ::v8::Local; -using ::v8::String; -using ::v8::Script; - -namespace i = ::v8::internal; - -TEST(MIPSFunctionCalls) { - // Disable compilation of natives. - i::FLAG_disable_native_files = true; - i::FLAG_full_compiler = false; - - v8::HandleScope scope; - LocalContext env; // from cctest.h - - const char* c_source = "function foo() { return 0x1234; }; foo();"; - Local<String> source = ::v8::String::New(c_source); - Local<Script> script = ::v8::Script::Compile(source); - CHECK_EQ(0x1234, script->Run()->Int32Value()); -} diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index 8ee40385a..96a181d7a 100755 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -1,4 +1,4 @@ -// Copyright 2006-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: @@ -31,6 +31,7 @@ #include "v8.h" +#include "isolate.h" #include "token.h" #include "scanner.h" #include "parser.h" @@ -136,8 +137,9 @@ TEST(ScanHTMLEndComments) { // Regression test. See: // http://code.google.com/p/chromium/issues/detail?id=53548 // Tests that --> is correctly interpreted as comment-to-end-of-line if there - // is only whitespace before it on the line, even after a multiline-comment - // comment. This was not the case if it occurred before the first real token + // is only whitespace before it on the line (with comments considered as + // whitespace, even a multiline-comment containing a newline). + // This was not the case if it occurred before the first real token // in the input. const char* tests[] = { // Before first real token. @@ -151,9 +153,19 @@ TEST(ScanHTMLEndComments) { NULL }; + const char* fail_tests[] = { + "x --> is eol-comment\nvar y = 37;\n", + "\"\\n\" --> is eol-comment\nvar y = 37;\n", + "x/* precomment */ --> is eol-comment\nvar y = 37;\n", + "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n", + "var x = 42; --> is eol-comment\nvar y = 37;\n", + "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n", + NULL + }; + // Parser/Scanner needs a stack limit. int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); for (int i = 0; tests[i]; i++) { @@ -162,6 +174,13 @@ TEST(ScanHTMLEndComments) { CHECK(data != NULL && !data->HasError()); delete data; } + + for (int i = 0; fail_tests[i]; i++) { + v8::ScriptData* data = + v8::ScriptData::PreCompile(fail_tests[i], i::StrLength(fail_tests[i])); + CHECK(data == NULL || data->HasError()); + delete data; + } } @@ -184,7 +203,7 @@ TEST(Preparsing) { v8::Persistent<v8::Context> context = v8::Context::New(); v8::Context::Scope context_scope(context); int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); // Source containing functions that might be lazily compiled and all types @@ -245,26 +264,26 @@ TEST(Preparsing) { TEST(StandAlonePreParser) { int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); const char* programs[] = { "{label: 42}", "var x = 42;", "function foo(x, y) { return x + y; }", - "native function foo(); return %ArgleBargle(glop);", + "%ArgleBargle(glop);", "var x = new new Function('this.x = 42');", NULL }; - uintptr_t stack_limit = i::StackGuard::real_climit(); + 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( reinterpret_cast<const i::byte*>(program), static_cast<unsigned>(strlen(program))); i::CompleteParserRecorder log; - i::V8JavaScriptScanner scanner; + i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); v8::preparser::PreParser::PreParseResult result = @@ -281,7 +300,7 @@ TEST(StandAlonePreParser) { TEST(RegressChromium62639) { int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); const char* program = "var x = 'something';\n" @@ -306,7 +325,7 @@ TEST(Regress928) { // the block could be lazily compiled, and an extra, unexpected, // entry was added to the data. int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); const char* program = @@ -342,7 +361,7 @@ TEST(Regress928) { TEST(PreParseOverflow) { int marker; - i::StackGuard::SetStackLimit( + i::Isolate::Current()->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); size_t kProgramSize = 1024 * 1024; @@ -351,13 +370,13 @@ TEST(PreParseOverflow) { memset(*program, '(', kProgramSize); program[kProgramSize] = '\0'; - uintptr_t stack_limit = i::StackGuard::real_climit(); + uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); i::Utf8ToUC16CharacterStream stream( reinterpret_cast<const i::byte*>(*program), static_cast<unsigned>(kProgramSize)); i::CompleteParserRecorder log; - i::V8JavaScriptScanner scanner; + i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); @@ -405,10 +424,10 @@ void TestCharacterStream(const char* ascii_source, } i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length)); i::Handle<i::String> ascii_string( - i::Factory::NewStringFromAscii(ascii_vector)); + FACTORY->NewStringFromAscii(ascii_vector)); TestExternalResource resource(*uc16_buffer, length); i::Handle<i::String> uc16_string( - i::Factory::NewExternalStringFromTwoByte(&resource)); + FACTORY->NewExternalStringFromTwoByte(&resource)); i::ExternalTwoByteStringUC16CharacterStream uc16_stream( i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end); @@ -575,7 +594,7 @@ void TestStreamScanner(i::UC16CharacterStream* stream, i::Token::Value* expected_tokens, int skip_pos = 0, // Zero means not skipping. int skip_to = 0) { - i::V8JavaScriptScanner scanner; + i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(stream); int i = 0; @@ -654,7 +673,7 @@ void TestScanRegExp(const char* re_source, const char* expected) { i::Utf8ToUC16CharacterStream stream( reinterpret_cast<const i::byte*>(re_source), static_cast<unsigned>(strlen(re_source))); - i::V8JavaScriptScanner scanner; + i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); i::Token::Value start = scanner.peek(); diff --git a/deps/v8/test/cctest/test-platform-linux.cc b/deps/v8/test/cctest/test-platform-linux.cc index e1a00e106..756b9473c 100644 --- a/deps/v8/test/cctest/test-platform-linux.cc +++ b/deps/v8/test/cctest/test-platform-linux.cc @@ -67,6 +67,7 @@ TEST(BusyLock) { TEST(VirtualMemory) { + OS::Setup(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/deps/v8/test/cctest/test-platform-tls.cc b/deps/v8/test/cctest/test-platform-tls.cc new file mode 100644 index 000000000..7f33aa2fb --- /dev/null +++ b/deps/v8/test/cctest/test-platform-tls.cc @@ -0,0 +1,66 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// +// Tests of fast TLS support. + +#include "v8.h" + +#include "cctest.h" +#include "checks.h" +#include "platform.h" + +using v8::internal::Thread; + +static const int kValueCount = 128; + +static Thread::LocalStorageKey keys[kValueCount]; + +static void* GetValue(int num) { + return reinterpret_cast<void*>(static_cast<intptr_t>(num + 1)); +} + +static void DoTest() { + for (int i = 0; i < kValueCount; i++) { + CHECK(!Thread::HasThreadLocal(keys[i])); + } + for (int i = 0; i < kValueCount; i++) { + Thread::SetThreadLocal(keys[i], GetValue(i)); + } + for (int i = 0; i < kValueCount; i++) { + CHECK(Thread::HasThreadLocal(keys[i])); + } + for (int i = 0; i < kValueCount; i++) { + CHECK_EQ(GetValue(i), Thread::GetThreadLocal(keys[i])); + CHECK_EQ(GetValue(i), Thread::GetExistingThreadLocal(keys[i])); + } + for (int i = 0; i < kValueCount; i++) { + Thread::SetThreadLocal(keys[i], GetValue(kValueCount - i - 1)); + } + for (int i = 0; i < kValueCount; i++) { + CHECK(Thread::HasThreadLocal(keys[i])); + } + for (int i = 0; i < kValueCount; i++) { + CHECK_EQ(GetValue(kValueCount - i - 1), + Thread::GetThreadLocal(keys[i])); + CHECK_EQ(GetValue(kValueCount - i - 1), + Thread::GetExistingThreadLocal(keys[i])); + } +} + +class TestThread : public Thread { + public: + TestThread() : Thread("TestThread") {} + + virtual void Run() { + DoTest(); + } +}; + +TEST(FastTLS) { + for (int i = 0; i < kValueCount; i++) { + keys[i] = Thread::CreateThreadLocalKey(); + } + DoTest(); + TestThread thread; + thread.Start(); + thread.Join(); +} diff --git a/deps/v8/test/cctest/test-platform-win32.cc b/deps/v8/test/cctest/test-platform-win32.cc index a5a6dd58a..9bd0014c6 100644 --- a/deps/v8/test/cctest/test-platform-win32.cc +++ b/deps/v8/test/cctest/test-platform-win32.cc @@ -13,6 +13,7 @@ using namespace ::v8::internal; TEST(VirtualMemory) { + OS::Setup(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc index c60d0720a..fbe5834e5 100644 --- a/deps/v8/test/cctest/test-profile-generator.cc +++ b/deps/v8/test/cctest/test-profile-generator.cc @@ -56,7 +56,7 @@ TEST(TokenEnumerator) { CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); } CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2)); - i::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); 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/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index 51fef7146..6588c68b7 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/deps/v8/test/cctest/test-regexp.cc @@ -45,6 +45,10 @@ #include "arm/macro-assembler-arm.h" #include "arm/regexp-macro-assembler-arm.h" #endif +#ifdef V8_TARGET_ARCH_MIPS +#include "mips/macro-assembler-mips.h" +#include "mips/regexp-macro-assembler-mips.h" +#endif #ifdef V8_TARGET_ARCH_X64 #include "x64/macro-assembler-x64.h" #include "x64/regexp-macro-assembler-x64.h" @@ -61,8 +65,8 @@ using namespace v8::internal; static bool CheckParse(const char* input) { V8::Initialize(NULL); v8::HandleScope scope; - ZoneScope zone_scope(DELETE_ON_EXIT); - FlatStringReader reader(CStrVector(input)); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + FlatStringReader reader(Isolate::Current(), CStrVector(input)); RegExpCompileData result; return v8::internal::RegExpParser::ParseRegExp(&reader, false, &result); } @@ -71,8 +75,8 @@ static bool CheckParse(const char* input) { static SmartPointer<const char> Parse(const char* input) { V8::Initialize(NULL); v8::HandleScope scope; - ZoneScope zone_scope(DELETE_ON_EXIT); - FlatStringReader reader(CStrVector(input)); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + FlatStringReader reader(Isolate::Current(), CStrVector(input)); RegExpCompileData result; CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); @@ -85,8 +89,8 @@ static bool CheckSimple(const char* input) { V8::Initialize(NULL); v8::HandleScope scope; unibrow::Utf8InputBuffer<> buffer(input, StrLength(input)); - ZoneScope zone_scope(DELETE_ON_EXIT); - FlatStringReader reader(CStrVector(input)); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + FlatStringReader reader(Isolate::Current(), CStrVector(input)); RegExpCompileData result; CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); @@ -103,8 +107,8 @@ static MinMaxPair CheckMinMaxMatch(const char* input) { V8::Initialize(NULL); v8::HandleScope scope; unibrow::Utf8InputBuffer<> buffer(input, StrLength(input)); - ZoneScope zone_scope(DELETE_ON_EXIT); - FlatStringReader reader(CStrVector(input)); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + FlatStringReader reader(Isolate::Current(), CStrVector(input)); RegExpCompileData result; CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result)); CHECK(result.tree != NULL); @@ -374,8 +378,8 @@ static void ExpectError(const char* input, const char* expected) { V8::Initialize(NULL); v8::HandleScope scope; - ZoneScope zone_scope(DELETE_ON_EXIT); - FlatStringReader reader(CStrVector(input)); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + FlatStringReader reader(Isolate::Current(), CStrVector(input)); RegExpCompileData result; CHECK(!v8::internal::RegExpParser::ParseRegExp(&reader, false, &result)); CHECK(result.tree == NULL); @@ -456,7 +460,7 @@ static bool NotWord(uc16 c) { static void TestCharacterClassEscapes(uc16 c, bool (pred)(uc16 c)) { - ZoneScope scope(DELETE_ON_EXIT); + ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); CharacterRange::AddClassEscape(c, ranges); for (unsigned i = 0; i < (1 << 16); i++) { @@ -471,6 +475,7 @@ static void TestCharacterClassEscapes(uc16 c, bool (pred)(uc16 c)) { TEST(CharacterClassEscapes) { + v8::internal::V8::Initialize(NULL); TestCharacterClassEscapes('.', IsRegExpNewline); TestCharacterClassEscapes('d', IsDigit); TestCharacterClassEscapes('D', NotDigit); @@ -483,12 +488,14 @@ TEST(CharacterClassEscapes) { static RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) { V8::Initialize(NULL); - FlatStringReader reader(CStrVector(input)); + Isolate* isolate = Isolate::Current(); + FlatStringReader reader(isolate, CStrVector(input)); RegExpCompileData compile_data; if (!v8::internal::RegExpParser::ParseRegExp(&reader, multiline, &compile_data)) return NULL; - Handle<String> pattern = Factory::NewStringFromUtf8(CStrVector(input)); + Handle<String> pattern = isolate->factory()-> + NewStringFromUtf8(CStrVector(input)); RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii); return compile_data.node; } @@ -499,7 +506,7 @@ static void Execute(const char* input, bool is_ascii, bool dot_output = false) { v8::HandleScope scope; - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); RegExpNode* node = Compile(input, multiline, is_ascii); USE(node); #ifdef DEBUG @@ -538,8 +545,9 @@ static unsigned PseudoRandom(int i, int j) { TEST(SplayTreeSimple) { + v8::internal::V8::Initialize(NULL); static const unsigned kLimit = 1000; - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); ZoneSplayTree<TestConfig> tree; bool seen[kLimit]; for (unsigned i = 0; i < kLimit; i++) seen[i] = false; @@ -590,6 +598,7 @@ TEST(SplayTreeSimple) { TEST(DispatchTableConstruction) { + v8::internal::V8::Initialize(NULL); // Initialize test data. static const int kLimit = 1000; static const int kRangeCount = 8; @@ -606,7 +615,7 @@ TEST(DispatchTableConstruction) { } } // Enter test data into dispatch table. - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); DispatchTable table; for (int i = 0; i < kRangeCount; i++) { uc16* range = ranges[i]; @@ -667,13 +676,13 @@ typedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler; #elif V8_TARGET_ARCH_ARM typedef RegExpMacroAssemblerARM ArchRegExpMacroAssembler; #elif V8_TARGET_ARCH_MIPS -typedef RegExpMacroAssembler ArchRegExpMacroAssembler; +typedef RegExpMacroAssemblerMIPS ArchRegExpMacroAssembler; #endif class ContextInitializer { public: ContextInitializer() - : env_(), scope_(), zone_(DELETE_ON_EXIT), stack_guard_() { + : env_(), scope_(), zone_(Isolate::Current(), DELETE_ON_EXIT) { env_ = v8::Context::New(); env_->Enter(); } @@ -685,7 +694,6 @@ class ContextInitializer { v8::Persistent<v8::Context> env_; v8::HandleScope scope_; v8::internal::ZoneScope zone_; - v8::internal::StackGuard stack_guard_; }; @@ -701,24 +709,26 @@ static ArchRegExpMacroAssembler::Result Execute(Code* code, start_offset, input_start, input_end, - captures); + captures, + Isolate::Current()); } TEST(MacroAssemblerNativeSuccess) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4); m.Succeed(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); int captures[4] = {42, 37, 87, 117}; - Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); + Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); const byte* start_adr = reinterpret_cast<const byte*>(seq_input->GetCharsAddress()); @@ -742,6 +752,7 @@ TEST(MacroAssemblerNativeSuccess) { TEST(MacroAssemblerNativeSimple) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4); @@ -757,12 +768,12 @@ TEST(MacroAssemblerNativeSimple) { m.Bind(&fail); m.Fail(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); int captures[4] = {42, 37, 87, 117}; - Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); + Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -780,7 +791,7 @@ TEST(MacroAssemblerNativeSimple) { CHECK_EQ(-1, captures[2]); CHECK_EQ(-1, captures[3]); - input = Factory::NewStringFromAscii(CStrVector("barbarbar")); + input = factory->NewStringFromAscii(CStrVector("barbarbar")); seq_input = Handle<SeqAsciiString>::cast(input); start_adr = seq_input->GetCharsAddress(); @@ -798,6 +809,7 @@ TEST(MacroAssemblerNativeSimple) { TEST(MacroAssemblerNativeSimpleUC16) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4); @@ -813,14 +825,14 @@ TEST(MacroAssemblerNativeSimpleUC16) { m.Bind(&fail); m.Fail(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("^foo")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo")); Handle<Object> code_object = m.GetCode(source); 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'}; Handle<String> input = - Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6)); + factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6)); Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -839,7 +851,7 @@ TEST(MacroAssemblerNativeSimpleUC16) { CHECK_EQ(-1, captures[3]); const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a', '\xa0'}; - input = Factory::NewStringFromTwoByte(Vector<const uc16>(input_data2, 9)); + input = factory->NewStringFromTwoByte(Vector<const uc16>(input_data2, 9)); seq_input = Handle<SeqTwoByteString>::cast(input); start_adr = seq_input->GetCharsAddress(); @@ -857,6 +869,7 @@ TEST(MacroAssemblerNativeSimpleUC16) { TEST(MacroAssemblerNativeBacktrack) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0); @@ -871,11 +884,11 @@ TEST(MacroAssemblerNativeBacktrack) { m.Bind(&backtrack); m.Fail(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("..........")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("..........")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); - Handle<String> input = Factory::NewStringFromAscii(CStrVector("foofoo")); + Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -894,6 +907,7 @@ TEST(MacroAssemblerNativeBacktrack) { TEST(MacroAssemblerNativeBackReferenceASCII) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4); @@ -912,11 +926,11 @@ TEST(MacroAssemblerNativeBackReferenceASCII) { m.Bind(&missing_match); m.Fail(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); - Handle<String> input = Factory::NewStringFromAscii(CStrVector("fooofo")); + Handle<String> input = factory->NewStringFromAscii(CStrVector("fooofo")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -940,6 +954,7 @@ TEST(MacroAssemblerNativeBackReferenceASCII) { TEST(MacroAssemblerNativeBackReferenceUC16) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4); @@ -958,13 +973,13 @@ TEST(MacroAssemblerNativeBackReferenceUC16) { m.Bind(&missing_match); m.Fail(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028}; Handle<String> input = - Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6)); + factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6)); Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -989,6 +1004,7 @@ TEST(MacroAssemblerNativeBackReferenceUC16) { TEST(MacroAssemblernativeAtStart) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0); @@ -1013,11 +1029,11 @@ TEST(MacroAssemblernativeAtStart) { m.CheckNotCharacter('b', &fail); m.Succeed(); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("(^f|ob)")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("(^f|ob)")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); - Handle<String> input = Factory::NewStringFromAscii(CStrVector("foobar")); + Handle<String> input = factory->NewStringFromAscii(CStrVector("foobar")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -1045,6 +1061,7 @@ TEST(MacroAssemblernativeAtStart) { TEST(MacroAssemblerNativeBackRefNoCase) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4); @@ -1071,12 +1088,12 @@ TEST(MacroAssemblerNativeBackRefNoCase) { m.Succeed(); Handle<String> source = - Factory::NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)")); + factory->NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); Handle<String> input = - Factory::NewStringFromAscii(CStrVector("aBcAbCABCxYzab")); + factory->NewStringFromAscii(CStrVector("aBcAbCABCxYzab")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -1101,6 +1118,7 @@ TEST(MacroAssemblerNativeBackRefNoCase) { TEST(MacroAssemblerNativeRegisters) { v8::V8::Initialize(); ContextInitializer initializer; + Factory* factory = Isolate::Current()->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 6); @@ -1169,13 +1187,13 @@ TEST(MacroAssemblerNativeRegisters) { m.Fail(); Handle<String> source = - Factory::NewStringFromAscii(CStrVector("<loop test>")); + factory->NewStringFromAscii(CStrVector("<loop test>")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); // String long enough for test (content doesn't matter). Handle<String> input = - Factory::NewStringFromAscii(CStrVector("foofoofoofoofoo")); + factory->NewStringFromAscii(CStrVector("foofoofoofoofoo")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -1201,6 +1219,8 @@ TEST(MacroAssemblerNativeRegisters) { TEST(MacroAssemblerStackOverflow) { v8::V8::Initialize(); ContextInitializer initializer; + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0); @@ -1210,13 +1230,13 @@ TEST(MacroAssemblerStackOverflow) { m.GoTo(&loop); Handle<String> source = - Factory::NewStringFromAscii(CStrVector("<stack overflow test>")); + factory->NewStringFromAscii(CStrVector("<stack overflow test>")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); // String long enough for test (content doesn't matter). Handle<String> input = - Factory::NewStringFromAscii(CStrVector("dummy")); + factory->NewStringFromAscii(CStrVector("dummy")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -1229,14 +1249,16 @@ TEST(MacroAssemblerStackOverflow) { NULL); CHECK_EQ(NativeRegExpMacroAssembler::EXCEPTION, result); - CHECK(Top::has_pending_exception()); - Top::clear_pending_exception(); + CHECK(isolate->has_pending_exception()); + isolate->clear_pending_exception(); } TEST(MacroAssemblerNativeLotsOfRegisters) { v8::V8::Initialize(); ContextInitializer initializer; + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 2); @@ -1254,13 +1276,13 @@ TEST(MacroAssemblerNativeLotsOfRegisters) { m.Succeed(); Handle<String> source = - Factory::NewStringFromAscii(CStrVector("<huge register space test>")); + factory->NewStringFromAscii(CStrVector("<huge register space test>")); Handle<Object> code_object = m.GetCode(source); Handle<Code> code = Handle<Code>::cast(code_object); // String long enough for test (content doesn't matter). Handle<String> input = - Factory::NewStringFromAscii(CStrVector("sample text")); + factory->NewStringFromAscii(CStrVector("sample text")); Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input); Address start_adr = seq_input->GetCharsAddress(); @@ -1277,7 +1299,7 @@ TEST(MacroAssemblerNativeLotsOfRegisters) { CHECK_EQ(0, captures[0]); CHECK_EQ(42, captures[1]); - Top::clear_pending_exception(); + isolate->clear_pending_exception(); } #else // V8_INTERPRETED_REGEXP @@ -1320,17 +1342,19 @@ TEST(MacroAssembler) { m.PopRegister(0); m.Fail(); - v8::HandleScope scope; + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope scope(isolate); - Handle<String> source = Factory::NewStringFromAscii(CStrVector("^f(o)o")); + Handle<String> source = factory->NewStringFromAscii(CStrVector("^f(o)o")); Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source)); int captures[5]; const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'}; Handle<String> f1_16 = - Factory::NewStringFromTwoByte(Vector<const uc16>(str1, 6)); + factory->NewStringFromTwoByte(Vector<const uc16>(str1, 6)); - CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0)); + CHECK(IrregexpInterpreter::Match(isolate, array, f1_16, captures, 0)); CHECK_EQ(0, captures[0]); CHECK_EQ(3, captures[1]); CHECK_EQ(1, captures[2]); @@ -1339,9 +1363,9 @@ TEST(MacroAssembler) { const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'}; Handle<String> f2_16 = - Factory::NewStringFromTwoByte(Vector<const uc16>(str2, 6)); + factory->NewStringFromTwoByte(Vector<const uc16>(str2, 6)); - CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0)); + CHECK(!IrregexpInterpreter::Match(isolate, array, f2_16, captures, 0)); CHECK_EQ(42, captures[0]); } @@ -1349,10 +1373,11 @@ TEST(MacroAssembler) { TEST(AddInverseToTable) { + v8::internal::V8::Initialize(NULL); static const int kLimit = 1000; static const int kRangeCount = 16; for (int t = 0; t < 10; t++) { - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(kRangeCount); for (int i = 0; i < kRangeCount; i++) { @@ -1373,7 +1398,7 @@ TEST(AddInverseToTable) { CHECK_EQ(is_on, set->Get(0) == false); } } - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(1); ranges->Add(CharacterRange(0xFFF0, 0xFFFE)); @@ -1486,7 +1511,7 @@ TEST(UncanonicalizeEquivalence) { static void TestRangeCaseIndependence(CharacterRange input, Vector<CharacterRange> expected) { - ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); int count = expected.length(); ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(count); input.AddCaseEquivalents(list, false); @@ -1507,6 +1532,7 @@ static void TestSimpleRangeCaseIndependence(CharacterRange input, TEST(CharacterRangeCaseIndependence) { + v8::internal::V8::Initialize(NULL); TestSimpleRangeCaseIndependence(CharacterRange::Singleton('a'), CharacterRange::Singleton('A')); TestSimpleRangeCaseIndependence(CharacterRange::Singleton('z'), @@ -1548,7 +1574,8 @@ static bool InClass(uc16 c, ZoneList<CharacterRange>* ranges) { TEST(CharClassDifference) { - ZoneScope zone_scope(DELETE_ON_EXIT); + v8::internal::V8::Initialize(NULL); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange>* base = new ZoneList<CharacterRange>(1); base->Add(CharacterRange::Everything()); Vector<const uc16> overlay = CharacterRange::GetWordBounds(); @@ -1574,7 +1601,8 @@ TEST(CharClassDifference) { TEST(CanonicalizeCharacterSets) { - ZoneScope scope(DELETE_ON_EXIT); + v8::internal::V8::Initialize(NULL); + ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(4); CharacterSet set(list); @@ -1644,7 +1672,8 @@ static bool CharacterInSet(ZoneList<CharacterRange>* set, uc16 value) { } TEST(CharacterRangeMerge) { - ZoneScope zone_scope(DELETE_ON_EXIT); + v8::internal::V8::Initialize(NULL); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); ZoneList<CharacterRange> l1(4); ZoneList<CharacterRange> l2(4); // Create all combinations of intersections of ranges, both singletons and diff --git a/deps/v8/test/cctest/test-reloc-info.cc b/deps/v8/test/cctest/test-reloc-info.cc index 2b9beac12..0378fb341 100644 --- a/deps/v8/test/cctest/test-reloc-info.cc +++ b/deps/v8/test/cctest/test-reloc-info.cc @@ -1,4 +1,4 @@ -// Copyright 2010 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: @@ -42,24 +42,31 @@ static void WriteRinfo(RelocInfoWriter* writer, // Tests that writing both types of positions and then reading either // or both works as expected. TEST(Positions) { - const int instr_size = 10 << 10; - const int reloc_size = 10 << 10; - const int buf_size = instr_size + reloc_size; - SmartPointer<byte> buf(new byte[buf_size]); - byte* pc = *buf; - CodeDesc desc = { *buf, buf_size, instr_size, reloc_size, NULL }; + const int code_size = 10 * KB; + int relocation_info_size = 10 * KB; + const int buffer_size = code_size + relocation_info_size; + SmartPointer<byte> buffer(new byte[buffer_size]); - RelocInfoWriter writer(*buf + buf_size, pc); + byte* pc = *buffer; + byte* buffer_end = *buffer + buffer_size; + + RelocInfoWriter writer(buffer_end, pc); + byte* relocation_info_end = buffer_end - relocation_info_size; for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; WriteRinfo(&writer, pc, mode, pos); + CHECK(writer.pos() - RelocInfoWriter::kMaxSize >= relocation_info_end); } + relocation_info_size = static_cast<int>(buffer_end - writer.pos()); + CodeDesc desc = { *buffer, buffer_size, code_size, + relocation_info_size, NULL }; + // Read only (non-statement) positions. { RelocIterator it(desc, RelocInfo::ModeMask(RelocInfo::POSITION)); - pc = *buf; + pc = *buffer; for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; @@ -76,7 +83,7 @@ TEST(Positions) { // Read only statement positions. { RelocIterator it(desc, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION)); - pc = *buf; + pc = *buffer; for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; @@ -93,7 +100,7 @@ TEST(Positions) { // Read both types of positions. { RelocIterator it(desc, RelocInfo::kPositionMask); - pc = *buf; + pc = *buffer; for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 80910c256..730d72a95 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -83,7 +83,7 @@ static int* counter_function(const char* name) { template <class T> static Address AddressOf(T id) { - return ExternalReference(id).address(); + return ExternalReference(id, i::Isolate::Current()).address(); } @@ -99,70 +99,75 @@ static int make_code(TypeCode type, int id) { TEST(ExternalReferenceEncoder) { - StatsTable::SetCounterFunction(counter_function); - Heap::Setup(false); + OS::Setup(); + Isolate* isolate = i::Isolate::Current(); + isolate->stats_table()->SetCounterFunction(counter_function); + HEAP->Setup(false); ExternalReferenceEncoder encoder; - CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode), - Encode(encoder, Builtins::ArrayCode)); + CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode), + Encode(encoder, Builtins::kArrayCode)); CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort), Encode(encoder, Runtime::kAbort)); CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty), Encode(encoder, IC_Utility(IC::kLoadCallbackProperty))); ExternalReference keyed_load_function_prototype = - ExternalReference(&Counters::keyed_load_function_prototype); + 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(); + 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(); + ExternalReference::address_of_stack_limit(isolate); CHECK_EQ(make_code(UNCLASSIFIED, 4), encoder.Encode(stack_limit_address.address())); ExternalReference real_stack_limit_address = - ExternalReference::address_of_real_stack_limit(); + ExternalReference::address_of_real_stack_limit(isolate); CHECK_EQ(make_code(UNCLASSIFIED, 5), encoder.Encode(real_stack_limit_address.address())); #ifdef ENABLE_DEBUGGER_SUPPORT CHECK_EQ(make_code(UNCLASSIFIED, 15), - encoder.Encode(ExternalReference::debug_break().address())); + encoder.Encode(ExternalReference::debug_break(isolate).address())); #endif // ENABLE_DEBUGGER_SUPPORT CHECK_EQ(make_code(UNCLASSIFIED, 10), - encoder.Encode(ExternalReference::new_space_start().address())); + encoder.Encode( + ExternalReference::new_space_start(isolate).address())); CHECK_EQ(make_code(UNCLASSIFIED, 3), - encoder.Encode(ExternalReference::roots_address().address())); + encoder.Encode(ExternalReference::roots_address(isolate).address())); } TEST(ExternalReferenceDecoder) { - StatsTable::SetCounterFunction(counter_function); - Heap::Setup(false); + OS::Setup(); + Isolate* isolate = i::Isolate::Current(); + isolate->stats_table()->SetCounterFunction(counter_function); + HEAP->Setup(false); ExternalReferenceDecoder decoder; - CHECK_EQ(AddressOf(Builtins::ArrayCode), - decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode))); + CHECK_EQ(AddressOf(Builtins::kArrayCode), + decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode))); CHECK_EQ(AddressOf(Runtime::kAbort), decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort))); CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)), decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty))); ExternalReference keyed_load_function = - ExternalReference(&Counters::keyed_load_function_prototype); + ExternalReference(isolate->counters()->keyed_load_function_prototype()); CHECK_EQ(keyed_load_function.address(), decoder.Decode( make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype))); - CHECK_EQ(ExternalReference::the_hole_value_location().address(), + CHECK_EQ(ExternalReference::the_hole_value_location(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 2))); - CHECK_EQ(ExternalReference::address_of_stack_limit().address(), + CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 4))); - CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(), + 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().address(), + CHECK_EQ(ExternalReference::debug_break(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 15))); #endif // ENABLE_DEBUGGER_SUPPORT - CHECK_EQ(ExternalReference::new_space_start().address(), + CHECK_EQ(ExternalReference::new_space_start(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 10))); } @@ -276,12 +281,12 @@ static void Deserialize() { static void SanityCheck() { v8::HandleScope scope; #ifdef DEBUG - Heap::Verify(); + HEAP->Verify(); #endif - CHECK(Top::global()->IsJSObject()); - CHECK(Top::global_context()->IsContext()); - CHECK(Heap::symbol_table()->IsSymbolTable()); - CHECK(!Factory::LookupAsciiSymbol("Empty")->IsFailure()); + CHECK(Isolate::Current()->global()->IsJSObject()); + CHECK(Isolate::Current()->global_context()->IsContext()); + CHECK(HEAP->symbol_table()->IsSymbolTable()); + CHECK(!FACTORY->LookupAsciiSymbol("Empty")->IsFailure()); } @@ -291,7 +296,6 @@ DEPENDENT_TEST(Deserialize, Serialize) { // serialize a snapshot in a VM that is booted from a snapshot. if (!Snapshot::IsEnabled()) { v8::HandleScope scope; - Deserialize(); v8::Persistent<v8::Context> env = v8::Context::New(); @@ -305,7 +309,6 @@ DEPENDENT_TEST(Deserialize, Serialize) { DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) { if (!Snapshot::IsEnabled()) { v8::HandleScope scope; - Deserialize(); v8::Persistent<v8::Context> env = v8::Context::New(); @@ -319,7 +322,6 @@ DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) { DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) { if (!Snapshot::IsEnabled()) { v8::HandleScope scope; - Deserialize(); v8::Persistent<v8::Context> env = v8::Context::New(); @@ -337,7 +339,6 @@ DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2, SerializeTwice) { if (!Snapshot::IsEnabled()) { v8::HandleScope scope; - Deserialize(); v8::Persistent<v8::Context> env = v8::Context::New(); @@ -361,11 +362,11 @@ TEST(PartialSerialization) { // Make sure all builtin scripts are cached. { HandleScope scope; for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { - Bootstrapper::NativesSourceLookup(i); + Isolate::Current()->bootstrapper()->NativesSourceLookup(i); } } - Heap::CollectAllGarbage(true); - Heap::CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(true); Object* raw_foo; { @@ -425,7 +426,7 @@ static void ReserveSpaceForPartialSnapshot(const char* file_name) { #undef fscanf #endif fclose(fp); - Heap::ReserveSpace(new_size, + HEAP->ReserveSpace(new_size, pointer_size, data_size, code_size, @@ -482,12 +483,12 @@ TEST(ContextSerialization) { // Make sure all builtin scripts are cached. { HandleScope scope; for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { - Bootstrapper::NativesSourceLookup(i); + Isolate::Current()->bootstrapper()->NativesSourceLookup(i); } } // 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(true); int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; Vector<char> startup_name = Vector<char>::New(file_name_length + 1); @@ -561,7 +562,7 @@ TEST(LinearAllocation) { for (int size = 1000; size < 5 * MB; size += size >> 1) { int new_space_size = (size < new_space_max) ? size : new_space_max; - Heap::ReserveSpace( + HEAP->ReserveSpace( new_space_size, size, // Old pointer space. size, // Old data space. @@ -584,7 +585,7 @@ TEST(LinearAllocation) { i + kSmallFixedArraySize <= new_space_size; i += kSmallFixedArraySize) { Object* obj = - Heap::AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked(); + HEAP->AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked(); if (new_last != NULL) { CHECK(reinterpret_cast<char*>(obj) == reinterpret_cast<char*>(new_last) + kSmallFixedArraySize); @@ -596,7 +597,7 @@ TEST(LinearAllocation) { for (int i = 0; i + kSmallFixedArraySize <= size; i += kSmallFixedArraySize) { - Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength, + Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; @@ -614,7 +615,7 @@ TEST(LinearAllocation) { Object* data_last = NULL; for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) { - Object* obj = Heap::AllocateRawAsciiString(kSmallStringLength, + Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallStringSize) % Page::kPageSize; @@ -632,7 +633,7 @@ TEST(LinearAllocation) { Object* map_last = NULL; for (int i = 0; i + kMapSize <= size; i += kMapSize) { - Object* obj = Heap::AllocateMap(JS_OBJECT_TYPE, + Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE, 42 * kPointerSize)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kMapSize) % Page::kPageSize; @@ -654,7 +655,7 @@ TEST(LinearAllocation) { AlwaysAllocateScope always; int large_object_array_length = (size - FixedArray::kHeaderSize) / kPointerSize; - Object* obj = Heap::AllocateFixedArray(large_object_array_length, + Object* obj = HEAP->AllocateFixedArray(large_object_array_length, TENURED)->ToObjectChecked(); CHECK(!obj->IsFailure()); } diff --git a/deps/v8/test/cctest/test-sockets.cc b/deps/v8/test/cctest/test-sockets.cc index 822a23fa9..4af55dbe9 100644 --- a/deps/v8/test/cctest/test-sockets.cc +++ b/deps/v8/test/cctest/test-sockets.cc @@ -10,8 +10,12 @@ using namespace ::v8::internal; class SocketListenerThread : public Thread { public: - explicit SocketListenerThread(int port, int data_size) - : port_(port), data_size_(data_size), server_(NULL), client_(NULL), + SocketListenerThread(int port, int data_size) + : Thread("SocketListenerThread"), + port_(port), + data_size_(data_size), + server_(NULL), + client_(NULL), listening_(OS::CreateSemaphore(0)) { data_ = new char[data_size_]; } diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc index 706c6bf9a..de0c41e2b 100644 --- a/deps/v8/test/cctest/test-spaces.cc +++ b/deps/v8/test/cctest/test-spaces.cc @@ -65,6 +65,8 @@ TEST(Page) { Address page_start = RoundUp(start, Page::kPageSize); Page* p = Page::FromAddress(page_start); + // Initialized Page has heap pointer, normally set by memory_allocator. + p->heap_ = HEAP; CHECK(p->address() == page_start); CHECK(p->is_valid()); @@ -90,37 +92,45 @@ TEST(Page) { TEST(MemoryAllocator) { - CHECK(Heap::ConfigureHeapDefault()); - CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize())); - - OldSpace faked_space(Heap::MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE); + OS::Setup(); + Isolate* isolate = Isolate::Current(); + CHECK(HEAP->ConfigureHeapDefault()); + CHECK(isolate->memory_allocator()->Setup(HEAP->MaxReserved(), + HEAP->MaxExecutableSize())); + + 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 = - MemoryAllocator::AllocatePages(requested, &allocated, &faked_space); + isolate->memory_allocator()->AllocatePages( + requested, &allocated, &faked_space); CHECK(first_page->is_valid()); CHECK(allocated == requested || allocated == requested - 1); total_pages += allocated; Page* last_page = first_page; for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space)); + CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space)); last_page = p; } // Again, we should get n or n - 1 pages. Page* others = - MemoryAllocator::AllocatePages(requested, &allocated, &faked_space); + isolate->memory_allocator()->AllocatePages( + requested, &allocated, &faked_space); CHECK(others->is_valid()); CHECK(allocated == requested || allocated == requested - 1); total_pages += allocated; - MemoryAllocator::SetNextPage(last_page, others); + isolate->memory_allocator()->SetNextPage(last_page, others); int page_count = 0; for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space)); + CHECK(isolate->memory_allocator()->IsPageInSpace(p, &faked_space)); page_count++; } CHECK(total_pages == page_count); @@ -131,31 +141,34 @@ TEST(MemoryAllocator) { // 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 = MemoryAllocator::FreePages(second_page); + Page* free_return = isolate->memory_allocator()->FreePages(second_page); CHECK(free_return == second_page); - MemoryAllocator::SetNextPage(first_page, free_return); + isolate->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 = MemoryAllocator::FreePages(first_page); + Page* invalid_page = isolate->memory_allocator()->FreePages(first_page); CHECK(!invalid_page->is_valid()); - MemoryAllocator::TearDown(); + isolate->memory_allocator()->TearDown(); } TEST(NewSpace) { - CHECK(Heap::ConfigureHeapDefault()); - CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize())); + OS::Setup(); + CHECK(HEAP->ConfigureHeapDefault()); + CHECK(Isolate::Current()->memory_allocator()->Setup( + HEAP->MaxReserved(), HEAP->MaxExecutableSize())); - NewSpace new_space; + NewSpace new_space(HEAP); void* chunk = - MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize()); + Isolate::Current()->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())); + 2 * HEAP->ReservedSemiSpaceSize()); + CHECK(new_space.Setup(start, 2 * HEAP->ReservedSemiSpaceSize())); CHECK(new_space.HasBeenSetup()); while (new_space.Available() >= Page::kMaxHeapObjectSize) { @@ -165,24 +178,28 @@ TEST(NewSpace) { } new_space.TearDown(); - MemoryAllocator::TearDown(); + Isolate::Current()->memory_allocator()->TearDown(); } TEST(OldSpace) { - CHECK(Heap::ConfigureHeapDefault()); - CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize())); + OS::Setup(); + CHECK(HEAP->ConfigureHeapDefault()); + CHECK(Isolate::Current()->memory_allocator()->Setup( + HEAP->MaxReserved(), HEAP->MaxExecutableSize())); - OldSpace* s = new OldSpace(Heap::MaxOldGenerationSize(), + OldSpace* s = new OldSpace(HEAP, + HEAP->MaxOldGenerationSize(), OLD_POINTER_SPACE, NOT_EXECUTABLE); CHECK(s != NULL); void* chunk = - MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize()); + Isolate::Current()->memory_allocator()->ReserveInitialChunk( + 4 * HEAP->ReservedSemiSpaceSize()); CHECK(chunk != NULL); Address start = static_cast<Address>(chunk); - size_t size = RoundUp(start, 2 * Heap::ReservedSemiSpaceSize()) - start; + size_t size = RoundUp(start, 2 * HEAP->ReservedSemiSpaceSize()) - start; CHECK(s->Setup(start, size)); @@ -192,14 +209,15 @@ TEST(OldSpace) { s->TearDown(); delete s; - MemoryAllocator::TearDown(); + Isolate::Current()->memory_allocator()->TearDown(); } TEST(LargeObjectSpace) { - CHECK(Heap::Setup(false)); + OS::Setup(); + CHECK(HEAP->Setup(false)); - LargeObjectSpace* lo = Heap::lo_space(); + LargeObjectSpace* lo = HEAP->lo_space(); CHECK(lo != NULL); Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0)); @@ -233,5 +251,5 @@ TEST(LargeObjectSpace) { lo->TearDown(); delete lo; - MemoryAllocator::TearDown(); + Isolate::Current()->memory_allocator()->TearDown(); } diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index 3f02b32b8..4d9b264e9 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -94,7 +94,7 @@ static void InitializeBuildingBlocks( buf[j] = gen() % 65536; } building_blocks[i] = - Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len)); + FACTORY->NewStringFromTwoByte(Vector<const uc16>(buf, len)); for (int j = 0; j < len; j++) { CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } @@ -106,19 +106,19 @@ static void InitializeBuildingBlocks( buf[j] = gen() % 128; } building_blocks[i] = - Factory::NewStringFromAscii(Vector<const char>(buf, len)); + FACTORY->NewStringFromAscii(Vector<const char>(buf, len)); for (int j = 0; j < len; j++) { CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } break; } case 2: { - uc16* buf = Zone::NewArray<uc16>(len); + uc16* buf = ZONE->NewArray<uc16>(len); for (int j = 0; j < len; j++) { buf[j] = gen() % 65536; } Resource* resource = new Resource(Vector<const uc16>(buf, len)); - building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource); + building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource); for (int j = 0; j < len; j++) { CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } @@ -130,7 +130,7 @@ static void InitializeBuildingBlocks( buf[j] = gen() % 128; } building_blocks[i] = - Factory::NewStringFromAscii(Vector<const char>(buf, len)); + FACTORY->NewStringFromAscii(Vector<const char>(buf, len)); for (int j = 0; j < len; j++) { CHECK_EQ(buf[j], building_blocks[i]->Get(j)); } @@ -145,9 +145,9 @@ static void InitializeBuildingBlocks( static Handle<String> ConstructLeft( Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS], int depth) { - Handle<String> answer = Factory::NewStringFromAscii(CStrVector("")); + Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector("")); for (int i = 0; i < depth; i++) { - answer = Factory::NewConsString( + answer = FACTORY->NewConsString( answer, building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]); } @@ -158,9 +158,9 @@ static Handle<String> ConstructLeft( static Handle<String> ConstructRight( Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS], int depth) { - Handle<String> answer = Factory::NewStringFromAscii(CStrVector("")); + Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector("")); for (int i = depth - 1; i >= 0; i--) { - answer = Factory::NewConsString( + answer = FACTORY->NewConsString( building_blocks[i % NUMBER_OF_BUILDING_BLOCKS], answer); } @@ -177,7 +177,7 @@ static Handle<String> ConstructBalancedHelper( return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]; } if (to - from == 2) { - return Factory::NewConsString( + return FACTORY->NewConsString( building_blocks[from % NUMBER_OF_BUILDING_BLOCKS], building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]); } @@ -185,7 +185,7 @@ static Handle<String> ConstructBalancedHelper( ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2)); Handle<String> part2 = ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to); - return Factory::NewConsString(part1, part2); + return FACTORY->NewConsString(part1, part2); } @@ -233,7 +233,7 @@ TEST(Traverse) { InitializeVM(); v8::HandleScope scope; Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]; - ZoneScope zone(DELETE_ON_EXIT); + ZoneScope zone(Isolate::Current(), DELETE_ON_EXIT); InitializeBuildingBlocks(building_blocks); Handle<String> flat = ConstructBalanced(building_blocks); FlattenString(flat); @@ -286,12 +286,12 @@ TEST(DeepAscii) { foo[i] = "foo "[i % 4]; } Handle<String> string = - Factory::NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH)); - Handle<String> foo_string = Factory::NewStringFromAscii(CStrVector("foo")); + FACTORY->NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH)); + Handle<String> foo_string = FACTORY->NewStringFromAscii(CStrVector("foo")); for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) { - string = Factory::NewConsString(string, foo_string); + string = FACTORY->NewConsString(string, foo_string); } - Handle<String> flat_string = Factory::NewConsString(string, foo_string); + Handle<String> flat_string = FACTORY->NewConsString(string, foo_string); FlattenString(flat_string); for (int i = 0; i < 500; i++) { @@ -348,7 +348,7 @@ TEST(Utf8Conversion) { TEST(ExternalShortStringAdd) { - ZoneScope zone(DELETE_ON_EXIT); + ZoneScope zone(Isolate::Current(), DELETE_ON_EXIT); InitializeVM(); v8::HandleScope handle_scope; @@ -365,7 +365,7 @@ TEST(ExternalShortStringAdd) { // Generate short ascii and non-ascii external strings. for (int i = 0; i <= kMaxLength; i++) { - char* ascii = Zone::NewArray<char>(i + 1); + char* ascii = ZONE->NewArray<char>(i + 1); for (int j = 0; j < i; j++) { ascii[j] = 'a'; } @@ -377,7 +377,7 @@ TEST(ExternalShortStringAdd) { v8::String::NewExternal(ascii_resource); ascii_external_strings->Set(v8::Integer::New(i), ascii_external_string); - uc16* non_ascii = Zone::NewArray<uc16>(i + 1); + uc16* non_ascii = ZONE->NewArray<uc16>(i + 1); for (int j = 0; j < i; j++) { non_ascii[j] = 0x1234; } @@ -439,7 +439,7 @@ TEST(CachedHashOverflow) { // We incorrectly allowed strings to be tagged as array indices even if their // values didn't fit in the hash field. // See http://code.google.com/p/v8/issues/detail?id=728 - ZoneScope zone(DELETE_ON_EXIT); + ZoneScope zone(Isolate::Current(), DELETE_ON_EXIT); InitializeVM(); v8::HandleScope handle_scope; @@ -459,10 +459,10 @@ TEST(CachedHashOverflow) { Handle<Smi> fortytwo(Smi::FromInt(42)); Handle<Smi> thirtyseven(Smi::FromInt(37)); Handle<Object> results[] = { - Factory::undefined_value(), + FACTORY->undefined_value(), fortytwo, - Factory::undefined_value(), - Factory::undefined_value(), + FACTORY->undefined_value(), + FACTORY->undefined_value(), thirtyseven, fortytwo, thirtyseven // Bug yielded 42 here. diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc index aed7466a0..1aa57e308 100644 --- a/deps/v8/test/cctest/test-thread-termination.cc +++ b/deps/v8/test/cctest/test-thread-termination.cc @@ -159,11 +159,18 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) { class TerminatorThread : public v8::internal::Thread { + public: + explicit TerminatorThread(i::Isolate* isolate) + : Thread("TerminatorThread"), + isolate_(reinterpret_cast<v8::Isolate*>(isolate)) { } void Run() { semaphore->Wait(); - CHECK(!v8::V8::IsExecutionTerminating()); - v8::V8::TerminateExecution(); + CHECK(!v8::V8::IsExecutionTerminating(isolate_)); + v8::V8::TerminateExecution(isolate_); } + + private: + v8::Isolate* isolate_; }; @@ -171,7 +178,7 @@ class TerminatorThread : public v8::internal::Thread { // from the side by another thread. TEST(TerminateOnlyV8ThreadFromOtherThread) { semaphore = v8::internal::OS::CreateSemaphore(0); - TerminatorThread thread; + TerminatorThread thread(i::Isolate::Current()); thread.Start(); v8::HandleScope scope; @@ -193,6 +200,7 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) { class LoopingThread : public v8::internal::Thread { public: + LoopingThread() : Thread("LoopingThread") { } void Run() { v8::Locker locker; v8::HandleScope scope; @@ -216,29 +224,37 @@ class LoopingThread : public v8::internal::Thread { }; -// Test that multiple threads using V8 can be terminated from another -// thread when using Lockers and preemption. -TEST(TerminateMultipleV8Threads) { +// Test that multiple threads using default isolate can be terminated +// from another thread when using Lockers and preemption. +TEST(TerminateMultipleV8ThreadsDefaultIsolate) { { v8::Locker locker; v8::V8::Initialize(); v8::Locker::StartPreemption(1); semaphore = v8::internal::OS::CreateSemaphore(0); } - LoopingThread thread1; - thread1.Start(); - LoopingThread thread2; - thread2.Start(); - // Wait until both threads have signaled the semaphore. - semaphore->Wait(); - semaphore->Wait(); + const int kThreads = 2; + i::List<LoopingThread*> threads(kThreads); + for (int i = 0; i < kThreads; i++) { + threads.Add(new LoopingThread()); + } + for (int i = 0; i < kThreads; i++) { + threads[i]->Start(); + } + // Wait until all threads have signaled the semaphore. + for (int i = 0; i < kThreads; i++) { + semaphore->Wait(); + } { v8::Locker locker; - v8::V8::TerminateExecution(thread1.GetV8ThreadId()); - v8::V8::TerminateExecution(thread2.GetV8ThreadId()); + for (int i = 0; i < kThreads; i++) { + v8::V8::TerminateExecution(threads[i]->GetV8ThreadId()); + } + } + for (int i = 0; i < kThreads; i++) { + threads[i]->Join(); + delete threads[i]; } - thread1.Join(); - thread2.Join(); delete semaphore; semaphore = NULL; diff --git a/deps/v8/test/cctest/test-threads.cc b/deps/v8/test/cctest/test-threads.cc index 0f48e248f..59d27ab7c 100644 --- a/deps/v8/test/cctest/test-threads.cc +++ b/deps/v8/test/cctest/test-threads.cc @@ -28,6 +28,7 @@ #include "v8.h" #include "platform.h" +#include "isolate.h" #include "cctest.h" @@ -64,6 +65,7 @@ static Turn turn = FILL_CACHE; class ThreadA: public v8::internal::Thread { public: + ThreadA() : Thread("ThreadA") { } void Run() { v8::Locker locker; v8::HandleScope scope; @@ -99,6 +101,7 @@ class ThreadA: public v8::internal::Thread { class ThreadB: public v8::internal::Thread { public: + ThreadB() : Thread("ThreadB") { } void Run() { do { { @@ -108,7 +111,7 @@ class ThreadB: public v8::internal::Thread { v8::Context::Scope context_scope(v8::Context::New()); // Clear the caches by forcing major GC. - v8::internal::Heap::CollectAllGarbage(false); + HEAP->CollectAllGarbage(false); turn = SECOND_TIME_FILL_CACHE; break; } @@ -134,3 +137,55 @@ TEST(JSFunctionResultCachesInTwoThreads) { CHECK_EQ(DONE, turn); } + +class ThreadIdValidationThread : public v8::internal::Thread { + public: + ThreadIdValidationThread(i::Thread* thread_to_start, + i::List<i::ThreadId>* refs, + unsigned int thread_no, + i::Semaphore* semaphore) + : Thread("ThreadRefValidationThread"), + refs_(refs), thread_no_(thread_no), thread_to_start_(thread_to_start), + semaphore_(semaphore) { + } + + void Run() { + i::ThreadId thread_id = i::ThreadId::Current(); + for (int i = 0; i < thread_no_; i++) { + CHECK(!(*refs_)[i].Equals(thread_id)); + } + CHECK(thread_id.IsValid()); + (*refs_)[thread_no_] = thread_id; + if (thread_to_start_ != NULL) { + thread_to_start_->Start(); + } + semaphore_->Signal(); + } + private: + i::List<i::ThreadId>* refs_; + int thread_no_; + i::Thread* thread_to_start_; + i::Semaphore* semaphore_; +}; + +TEST(ThreadIdValidation) { + const int kNThreads = 100; + i::List<ThreadIdValidationThread*> threads(kNThreads); + i::List<i::ThreadId> refs(kNThreads); + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); + ThreadIdValidationThread* prev = NULL; + for (int i = kNThreads - 1; i >= 0; i--) { + ThreadIdValidationThread* newThread = + new ThreadIdValidationThread(prev, &refs, i, semaphore); + threads.Add(newThread); + prev = newThread; + refs.Add(i::ThreadId::Invalid()); + } + prev->Start(); + for (int i = 0; i < kNThreads; i++) { + semaphore->Wait(); + } + for (int i = 0; i < kNThreads; i++) { + delete threads[i]; + } +} diff --git a/deps/v8/test/cctest/test-type-info.cc b/deps/v8/test/cctest/test-type-info.cc deleted file mode 100644 index 59dd83d1f..000000000 --- a/deps/v8/test/cctest/test-type-info.cc +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - - -#include "cctest.h" -#include "type-info.h" - -namespace v8 { -namespace internal { - -TEST(ThreeBitRepresentation) { - // Numeric types and unknown should fit into the short - // representation. - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Unknown().ThreeBitRepresentation()).IsUnknown()); - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Number().ThreeBitRepresentation()).IsNumber()); - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Integer32().ThreeBitRepresentation()).IsInteger32()); - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Smi().ThreeBitRepresentation()).IsSmi()); - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Double().ThreeBitRepresentation()).IsDouble()); - - // Other types should map to unknown. - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::Primitive().ThreeBitRepresentation()).IsUnknown()); - CHECK(TypeInfo::ExpandedRepresentation( - TypeInfo::String().ThreeBitRepresentation()).IsUnknown()); -} - -} } // namespace v8::internal diff --git a/deps/v8/test/cctest/test-utils.cc b/deps/v8/test/cctest/test-utils.cc index b48dcb8b6..e13685830 100644 --- a/deps/v8/test/cctest/test-utils.cc +++ b/deps/v8/test/cctest/test-utils.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: @@ -29,8 +29,9 @@ #include "v8.h" -#include "platform.h" #include "cctest.h" +#include "platform.h" +#include "utils-inl.h" using namespace v8::internal; @@ -89,8 +90,8 @@ void TestMemCopy(Vector<byte> src, memset(dst.start(), 0xFF, dst.length()); byte* to = dst.start() + 32 + destination_alignment; byte* from = src.start() + source_alignment; - int length = kMinComplexMemCopy + length_alignment; - MemCopy(to, from, static_cast<size_t>(length)); + int length = OS::kMinComplexMemCopy + length_alignment; + OS::MemCopy(to, from, static_cast<size_t>(length)); printf("[%d,%d,%d]\n", source_alignment, destination_alignment, length_alignment); for (int i = 0; i < length; i++) { @@ -103,8 +104,9 @@ void TestMemCopy(Vector<byte> src, TEST(MemCopy) { - V8::Initialize(NULL); - const int N = kMinComplexMemCopy + 128; + v8::V8::Initialize(); + 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/deps/v8/test/cctest/testcfg.py b/deps/v8/test/cctest/testcfg.py index b15342eda..a137275ff 100644 --- a/deps/v8/test/cctest/testcfg.py +++ b/deps/v8/test/cctest/testcfg.py @@ -34,11 +34,12 @@ import utils class CcTestCase(test.TestCase): - def __init__(self, path, executable, mode, raw_name, dependency, context): + def __init__(self, path, executable, mode, raw_name, dependency, context, variant_flags): super(CcTestCase, self).__init__(context, path, mode) self.executable = executable self.raw_name = raw_name self.dependency = dependency + self.variant_flags = variant_flags def GetLabel(self): return "%s %s %s" % (self.mode, self.path[-2], self.path[-1]) @@ -49,6 +50,8 @@ class CcTestCase(test.TestCase): def BuildCommand(self, name): serialization_file = join('obj', 'test', self.mode, 'serdes') serialization_file += '_' + self.GetName() + serialization_file = join(self.context.buildspace, serialization_file) + serialization_file += ''.join(self.variant_flags).replace('-', '_') serialization_option = '--testing_serialization_file=' + serialization_file result = [ self.executable, name, serialization_option ] result += self.context.GetVmFlags(self, self.mode) @@ -74,10 +77,11 @@ class CcTestConfiguration(test.TestConfiguration): def GetBuildRequirements(self): return ['cctests'] - def ListTests(self, current_path, path, mode): + def ListTests(self, current_path, path, mode, variant_flags): executable = join('obj', 'test', mode, 'cctest') if utils.IsWindows(): executable += '.exe' + executable = join(self.context.buildspace, executable) output = test.Execute([executable, '--list'], self.context) if output.exit_code != 0: print output.stdout @@ -91,7 +95,7 @@ class CcTestConfiguration(test.TestConfiguration): if dependency != '': dependency = relative_path[0] + '/' + dependency if self.Contains(path, full_path): - result.append(CcTestCase(full_path, executable, mode, raw_test, dependency, self.context)) + result.append(CcTestCase(full_path, executable, mode, raw_test, dependency, self.context, variant_flags)) result.sort() return result |