diff options
author | Timothy J Fontaine <tjfontaine@gmail.com> | 2013-10-22 15:14:25 -0700 |
---|---|---|
committer | Timothy J Fontaine <tjfontaine@gmail.com> | 2013-10-23 09:17:31 -0700 |
commit | a53c763c16eeabb0901a05dbcf38a72fa96d2f26 (patch) | |
tree | 309bf250e1521cedf0e945d7a7629db511e64498 /deps/v8/test | |
parent | 54910044b33a6405c72ad085915a55c575c027fc (diff) | |
download | node-new-a53c763c16eeabb0901a05dbcf38a72fa96d2f26.tar.gz |
v8: upgrade 3.21.18.3
Diffstat (limited to 'deps/v8/test')
102 files changed, 5006 insertions, 1701 deletions
diff --git a/deps/v8/test/cctest/cctest.cc b/deps/v8/test/cctest/cctest.cc index a2caf0f3ba..616c6a3a6b 100644 --- a/deps/v8/test/cctest/cctest.cc +++ b/deps/v8/test/cctest/cctest.cc @@ -100,16 +100,22 @@ v8::Isolate* CcTest::default_isolate_; class CcTestArrayBufferAllocator : public v8::ArrayBuffer::Allocator { virtual void* Allocate(size_t length) { return malloc(length); } + virtual void* AllocateUninitialized(size_t length) { return malloc(length); } virtual void Free(void* data, size_t length) { free(data); } // TODO(dslomov): Remove when v8:2823 is fixed. virtual void Free(void* data) { UNREACHABLE(); } }; +static void SuggestTestHarness(int tests) { + if (tests == 0) return; + printf("Running multiple tests in sequence is deprecated and may cause " + "bogus failure. Consider using tools/run-tests.py instead.\n"); +} + + int main(int argc, char* argv[]) { v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true); - v8::internal::FLAG_harmony_array_buffer = true; - v8::internal::FLAG_harmony_typed_arrays = true; CcTestArrayBufferAllocator array_buffer_allocator; v8::V8::SetArrayBufferAllocator(&array_buffer_allocator); @@ -138,8 +144,8 @@ int main(int argc, char* argv[]) { if (test->enabled() && strcmp(test->file(), file) == 0 && strcmp(test->name(), name) == 0) { + SuggestTestHarness(tests_run++); test->Run(); - tests_run++; } test = test->prev(); } @@ -152,8 +158,8 @@ int main(int argc, char* argv[]) { if (test->enabled() && (strcmp(test->file(), file_or_name) == 0 || strcmp(test->name(), file_or_name) == 0)) { + SuggestTestHarness(tests_run++); test->Run(); - tests_run++; } test = test->prev(); } diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp index 9df5c7bccc..ee7ffad6d3 100644 --- a/deps/v8/test/cctest/cctest.gyp +++ b/deps/v8/test/cctest/cctest.gyp @@ -55,7 +55,9 @@ 'test-bignum-dtoa.cc', 'test-circular-queue.cc', 'test-compiler.cc', + 'test-condition-variable.cc', 'test-conversions.cc', + 'test-cpu.cc', 'test-cpu-profiler.cc', 'test-dataflow.cc', 'test-date.cc', @@ -79,28 +81,32 @@ 'test-heap-profiler.cc', 'test-list.cc', 'test-liveedit.cc', - 'test-lock.cc', 'test-lockers.cc', 'test-log.cc', 'test-mark-compact.cc', + 'test-mutex.cc', 'test-object-observe.cc', 'test-parsing.cc', 'test-platform.cc', 'test-platform-tls.cc', 'test-profile-generator.cc', 'test-random.cc', + 'test-random-number-generator.cc', 'test-regexp.cc', 'test-reloc-info.cc', + 'test-semaphore.cc', 'test-serialize.cc', - 'test-sockets.cc', + 'test-socket.cc', 'test-spaces.cc', 'test-strings.cc', 'test-symbols.cc', 'test-strtod.cc', 'test-thread-termination.cc', 'test-threads.cc', + 'test-time.cc', 'test-types.cc', 'test-unbound-queue.cc', + 'test-unique.cc', 'test-utils.cc', 'test-version.cc', 'test-weakmaps.cc', @@ -113,6 +119,7 @@ 'test-assembler-ia32.cc', 'test-code-stubs.cc', 'test-code-stubs-ia32.cc', + 'test-cpu-ia32.cc', 'test-disasm-ia32.cc', 'test-log-stack-tracer.cc' ], @@ -122,6 +129,7 @@ 'test-assembler-x64.cc', 'test-code-stubs.cc', 'test-code-stubs-x64.cc', + 'test-cpu-x64.cc', 'test-macro-assembler-x64.cc', 'test-log-stack-tracer.cc' ], @@ -129,6 +137,8 @@ ['v8_target_arch=="arm"', { 'sources': [ 'test-assembler-arm.cc', + 'test-code-stubs.cc', + 'test-code-stubs-arm.cc', 'test-disasm-arm.cc' ], }], diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h index 193126a081..ceb97743eb 100644 --- a/deps/v8/test/cctest/cctest.h +++ b/deps/v8/test/cctest/cctest.h @@ -71,6 +71,10 @@ typedef v8::internal::EnumSet<CcTestExtensionIds> CcTestExtensionFlags; EXTENSION_LIST(DEFINE_EXTENSION_FLAG) #undef DEFINE_EXTENSION_FLAG +// Temporary macros for accessing current isolate and its subobjects. +// They provide better readability, especially when used a lot in the code. +#define HEAP (v8::internal::Isolate::Current()->heap()) + class CcTest { public: typedef void (TestFunction)(); @@ -91,6 +95,10 @@ class CcTest { static v8::Isolate* isolate() { return default_isolate_; } + static i::Isolate* i_isolate() { + return reinterpret_cast<i::Isolate*>(default_isolate_); + } + // Helper function to initialize the VM. static void InitializeVM(CcTestExtensionFlags extensions = NO_EXTENSIONS); @@ -144,10 +152,10 @@ class ApiTestFuzzer: public v8::internal::Thread { explicit ApiTestFuzzer(int num) : Thread("ApiTestFuzzer"), test_number_(num), - gate_(v8::internal::OS::CreateSemaphore(0)), + gate_(0), active_(true) { } - ~ApiTestFuzzer() { delete gate_; } + ~ApiTestFuzzer() {} static bool fuzzing_; static int tests_being_run_; @@ -155,11 +163,11 @@ class ApiTestFuzzer: public v8::internal::Thread { static int active_tests_; static bool NextThread(); int test_number_; - v8::internal::Semaphore* gate_; + v8::internal::Semaphore gate_; bool active_; void ContextSwitch(); static int GetNextTestNumber(); - static v8::internal::Semaphore* all_tests_done_; + static v8::internal::Semaphore all_tests_done_; }; diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 0d3ff150c6..85661098b2 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -34,6 +34,10 @@ test-api/Bug*: FAIL # BUG(382): Weird test. Can't guarantee that it never times out. test-api/ApplyInterruption: PASS || TIMEOUT +# TODO(mstarzinger): Fail gracefully on multiple V8::Dispose calls. +test-api/InitializeAndDisposeOnce: SKIP +test-api/InitializeAndDisposeMultiple: SKIP + # 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 @@ -52,6 +56,9 @@ test-weaksets/WeakSet_Shrinking: FAIL # Boot up memory use is bloated in debug mode. test-mark-compact/BootUpMemoryUse: PASS, PASS || FAIL if $mode == debug +# Some CPU profiler tests are flaky. +test-cpu-profiler/*: PASS || FLAKY + ############################################################################## [ $arch == arm ] @@ -70,6 +77,8 @@ test-serialize/DeserializeFromSecondSerializationAndRunScript2: SKIP test-serialize/DeserializeAndRunScript2: SKIP test-serialize/DeserializeFromSecondSerialization: SKIP +# BUG(2874): Threading problems. +test-api/*: PASS || FLAKY ############################################################################## [ $arch == mipsel ] @@ -113,7 +122,10 @@ test-log/ProfLazyMode: SKIP # Native Client doesn't support sockets. test-debug/DebuggerAgent: SKIP test-debug/DebuggerAgentProtocolOverflowHeader: SKIP -test-sockets/Socket: SKIP +test-socket/Socket: SKIP # Profiling doesn't work on Native Client. test-cpu-profiler/*: SKIP + +# Fails since 16322 (new test). +test-code-stubs-arm/ConvertDToI: SKIP diff --git a/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js b/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js index 05643bfb8a..522a3726ea 100644 --- a/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js +++ b/deps/v8/test/cctest/log-eq-of-logging-and-traversal.js @@ -39,7 +39,7 @@ function parseState(s) { function LogProcessor() { LogReader.call(this, { 'code-creation': { - parsers: [null, parseInt, parseInt, null, 'var-args'], + parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'], processor: this.processCodeCreation }, 'code-move': { parsers: [parseInt, parseInt], processor: this.processCodeMove }, @@ -55,8 +55,12 @@ function LogProcessor() { LogProcessor.prototype.__proto__ = LogReader.prototype; LogProcessor.prototype.processCodeCreation = function( - type, start, size, name, maybe_func) { + type, kind, start, size, name, maybe_func) { if (type != "LazyCompile" && type != "Script" && type != "Function") return; + // Scripts will compile into anonymous functions starting at 1:1. Adjust the + // name here so that it matches corrsponding function's name during the heap + // traversal. + if (type == "Script") name = " :1:1"; // Discard types to avoid discrepancies in "LazyCompile" vs. "Function". type = ""; if (maybe_func.length) { diff --git a/deps/v8/test/cctest/test-accessors.cc b/deps/v8/test/cctest/test-accessors.cc index 7d96ea64c2..2aaac922bf 100644 --- a/deps/v8/test/cctest/test-accessors.cc +++ b/deps/v8/test/cctest/test-accessors.cc @@ -41,7 +41,6 @@ using ::v8::Local; using ::v8::String; using ::v8::Script; using ::v8::Function; -using ::v8::AccessorInfo; using ::v8::Extension; static void handle_property(Local<String> name, @@ -50,18 +49,51 @@ static void handle_property(Local<String> name, info.GetReturnValue().Set(v8_num(900)); } +static void handle_property_2(Local<String> name, + const v8::PropertyCallbackInfo<v8::Value>& info) { + ApiTestFuzzer::Fuzz(); + info.GetReturnValue().Set(v8_num(902)); +} + + +static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) { + ApiTestFuzzer::Fuzz(); + CHECK_EQ(0, info.Length()); + info.GetReturnValue().Set(v8_num(907)); +} + THREADED_TEST(PropertyHandler) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property); + Local<v8::FunctionTemplate> getter_templ = + v8::FunctionTemplate::New(handle_property); + getter_templ->SetLength(0); + fun_templ-> + InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ); + fun_templ->InstanceTemplate()-> + SetNativeDataProperty(v8_str("instance_foo"), handle_property); + fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2); Local<Function> fun = fun_templ->GetFunction(); env->Global()->Set(v8_str("Fun"), fun); - Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;"); + Local<Script> getter; + Local<Script> setter; + // check function instance accessors + getter = v8_compile("var obj = new Fun(); obj.instance_foo;"); CHECK_EQ(900, getter->Run()->Int32Value()); - Local<Script> setter = v8_compile("obj.foo = 901;"); + setter = v8_compile("obj.instance_foo = 901;"); CHECK_EQ(901, setter->Run()->Int32Value()); + getter = v8_compile("obj.bar;"); + CHECK_EQ(907, getter->Run()->Int32Value()); + setter = v8_compile("obj.bar = 908;"); + CHECK_EQ(908, setter->Run()->Int32Value()); + // check function static accessors + getter = v8_compile("Fun.object_foo;"); + CHECK_EQ(902, getter->Run()->Int32Value()); + setter = v8_compile("Fun.object_foo = 903;"); + CHECK_EQ(903, setter->Run()->Int32Value()); } @@ -109,30 +141,53 @@ THREADED_TEST(GlobalVariableAccess) { } -static int x_register = 0; +static int x_register[2] = {0, 0}; static v8::Handle<v8::Object> x_receiver; static v8::Handle<v8::Object> x_holder; - -static void XGetter(Local<String> name, - const v8::PropertyCallbackInfo<v8::Value>& info) { +template<class Info> +static void XGetter(const Info& info, int offset) { ApiTestFuzzer::Fuzz(); v8::Isolate* isolate = v8::Isolate::GetCurrent(); CHECK_EQ(isolate, info.GetIsolate()); CHECK_EQ(x_receiver, info.This()); + info.GetReturnValue().Set(v8_num(x_register[offset])); +} + + +static void XGetter(Local<String> name, + const v8::PropertyCallbackInfo<v8::Value>& info) { CHECK_EQ(x_holder, info.Holder()); - info.GetReturnValue().Set(v8_num(x_register)); + XGetter(info, 0); } -static void XSetter(Local<String> name, - Local<Value> value, - const v8::PropertyCallbackInfo<void>& info) { +static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + CHECK_EQ(x_receiver, info.Holder()); + XGetter(info, 1); +} + + +template<class Info> +static void XSetter(Local<Value> value, const Info& info, int offset) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); CHECK_EQ(isolate, info.GetIsolate()); CHECK_EQ(x_holder, info.This()); CHECK_EQ(x_holder, info.Holder()); - x_register = value->Int32Value(); + x_register[offset] = value->Int32Value(); +} + + +static void XSetter(Local<String> name, + Local<Value> value, + const v8::PropertyCallbackInfo<void>& info) { + XSetter(value, info, 0); +} + + +static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + CHECK_EQ(1, info.Length()); + XSetter(info[0], info, 1); } @@ -140,7 +195,10 @@ THREADED_TEST(AccessorIC) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(); - obj->SetAccessor(v8_str("x"), XGetter, XSetter); + obj->SetAccessor(v8_str("x0"), XGetter, XSetter); + obj->SetAccessorProperty(v8_str("x1"), + v8::FunctionTemplate::New(XGetter), + v8::FunctionTemplate::New(XSetter)); x_holder = obj->NewInstance(); context->Global()->Set(v8_str("holder"), x_holder); x_receiver = v8::Object::New(); @@ -148,15 +206,23 @@ THREADED_TEST(AccessorIC) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun( "obj.__proto__ = holder;" "var result = [];" + "var key_0 = 'x0';" + "var key_1 = 'x1';" "for (var i = 0; i < 10; i++) {" - " holder.x = i;" - " result.push(obj.x);" + " holder.x0 = i;" + " result.push(obj.x0);" + " holder.x1 = i;" + " result.push(obj.x1);" + " holder[key_0] = i;" + " result.push(obj[key_0]);" + " holder[key_1] = i;" + " result.push(obj[key_1]);" "}" "result")); - CHECK_EQ(10, array->Length()); - for (int i = 0; i < 10; i++) { + CHECK_EQ(40, array->Length()); + for (int i = 0; i < 40; i++) { v8::Handle<Value> entry = array->Get(v8::Integer::New(i)); - CHECK_EQ(v8::Integer::New(i), entry); + CHECK_EQ(v8::Integer::New(i/4), entry); } } @@ -422,7 +488,8 @@ THREADED_TEST(StackIteration) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(); - i::StringStream::ClearMentionedObjectCache(); + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate()); + i::StringStream::ClearMentionedObjectCache(isolate); obj->SetAccessor(v8_str("xxx"), StackCheck); env->Global()->Set(v8_str("obj"), obj->NewInstance()); Script::Compile(String::New( @@ -485,3 +552,18 @@ THREADED_TEST(JSONStringifyNamedInterceptorObject) { v8::Handle<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}"); CHECK(CompileRun("JSON.stringify(obj)")->Equals(expected)); } + + +THREADED_TEST(CrossContextAccess) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + v8::Handle<v8::Function> fun = v8::Function::New(isolate, handle_property); + LocalContext switch_context; + switch_context->Global()->Set(v8_str("fun"), fun); + v8::TryCatch try_catch; + CompileRun( + "var o = Object.create(null, { n: { get:fun } });" + "for (var i = 0; i < 10; i++) o.n;"); + CHECK(!try_catch.HasCaught()); +} diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc index d316c8e49f..f4f13d0d83 100644 --- a/deps/v8/test/cctest/test-alloc.cc +++ b/deps/v8/test/cctest/test-alloc.cc @@ -90,7 +90,7 @@ static MaybeObject* AllocateAfterFailures() { static Handle<Object> Test() { - CALL_HEAP_FUNCTION(ISOLATE, AllocateAfterFailures(), Object); + CALL_HEAP_FUNCTION(Isolate::Current(), AllocateAfterFailures(), Object); } @@ -104,7 +104,7 @@ TEST(StressHandles) { } -static MaybeObject* TestAccessorGet(Object* object, void*) { +static MaybeObject* TestAccessorGet(Isolate* isolate, Object* object, void*) { return AllocateAfterFailures(); } @@ -186,10 +186,9 @@ class Block { TEST(CodeRange) { const int code_range_size = 32*MB; - OS::SetUp(); - Isolate::Current()->InitializeLoggingAndCounters(); - CodeRange* code_range = new CodeRange(Isolate::Current()); - code_range->SetUp(code_range_size); + CcTest::InitializeVM(); + CodeRange code_range(reinterpret_cast<Isolate*>(CcTest::isolate())); + code_range.SetUp(code_range_size); int current_allocated = 0; int total_allocated = 0; List<Block> blocks(1000); @@ -205,9 +204,9 @@ TEST(CodeRange) { (Page::kMaxNonCodeHeapObjectSize << (Pseudorandom() % 3)) + Pseudorandom() % 5000 + 1; size_t allocated = 0; - Address base = code_range->AllocateRawMemory(requested, - requested, - &allocated); + Address base = code_range.AllocateRawMemory(requested, + requested, + &allocated); CHECK(base != NULL); blocks.Add(Block(base, static_cast<int>(allocated))); current_allocated += static_cast<int>(allocated); @@ -215,7 +214,7 @@ TEST(CodeRange) { } else { // Free a block. int index = Pseudorandom() % blocks.length(); - code_range->FreeRawMemory(blocks[index].base, blocks[index].size); + code_range.FreeRawMemory(blocks[index].base, blocks[index].size); current_allocated -= blocks[index].size; if (index < blocks.length() - 1) { blocks[index] = blocks.RemoveLast(); @@ -225,6 +224,5 @@ TEST(CodeRange) { } } - code_range->TearDown(); - delete code_range; + code_range.TearDown(); } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 55d376d154..f4e40cdd38 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -25,17 +25,17 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <limits.h> - -#ifndef WIN32 -#include <signal.h> // kill -#include <unistd.h> // getpid -#endif // WIN32 +#include <climits> +#include <csignal> #include <string> #include <map> #include "v8.h" +#if V8_OS_POSIX +#include <unistd.h> // NOLINT +#endif + #include "api.h" #include "arguments.h" #include "cctest.h" @@ -53,8 +53,6 @@ static const bool kLogThreading = false; -using ::v8::AccessorInfo; -using ::v8::Arguments; using ::v8::Boolean; using ::v8::BooleanObject; using ::v8::Context; @@ -143,10 +141,13 @@ static void ExpectUndefined(const char* code) { static int signature_callback_count; +static Local<Value> signature_expected_receiver; static void IncrementingSignatureCallback( const v8::FunctionCallbackInfo<v8::Value>& args) { ApiTestFuzzer::Fuzz(); signature_callback_count++; + CHECK_EQ(signature_expected_receiver, args.Holder()); + CHECK_EQ(signature_expected_receiver, args.This()); v8::Handle<v8::Array> result = v8::Array::New(args.Length()); for (int i = 0; i < args.Length(); i++) result->Set(v8::Integer::New(i), args[i]); @@ -165,6 +166,24 @@ static void SignatureCallback( } +// Tests that call v8::V8::Dispose() cannot be threaded. +TEST(InitializeAndDisposeOnce) { + CHECK(v8::V8::Initialize()); + CHECK(v8::V8::Dispose()); +} + + +// Tests that call v8::V8::Dispose() cannot be threaded. +TEST(InitializeAndDisposeMultiple) { + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose()); + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize()); + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose()); + // TODO(mstarzinger): This should fail gracefully instead of asserting. + // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize()); + for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose()); +} + + THREADED_TEST(Handles) { v8::HandleScope scope(v8::Isolate::GetCurrent()); Local<Context> local_env; @@ -205,47 +224,98 @@ THREADED_TEST(IsolateOfContext) { } +static void TestSignature(const char* loop_js, Local<Value> receiver) { + i::ScopedVector<char> source(200); + i::OS::SNPrintF(source, + "for (var i = 0; i < 10; i++) {" + " %s" + "}", + loop_js); + signature_callback_count = 0; + signature_expected_receiver = receiver; + bool expected_to_throw = receiver.IsEmpty(); + v8::TryCatch try_catch; + CompileRun(source.start()); + CHECK_EQ(expected_to_throw, try_catch.HasCaught()); + if (!expected_to_throw) { + CHECK_EQ(10, signature_callback_count); + } else { + CHECK_EQ(v8_str("TypeError: Illegal invocation"), + try_catch.Exception()->ToString()); + } +} + + THREADED_TEST(ReceiverSignature) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); + // Setup templates. v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(); v8::Handle<v8::Signature> sig = v8::Signature::New(fun); - fun->PrototypeTemplate()->Set( - v8_str("m"), - v8::FunctionTemplate::New(IncrementingSignatureCallback, - v8::Handle<Value>(), - sig)); - env->Global()->Set(v8_str("Fun"), fun->GetFunction()); - signature_callback_count = 0; - CompileRun( - "var o = new Fun();" - "o.m();"); - CHECK_EQ(1, signature_callback_count); + v8::Handle<v8::FunctionTemplate> callback_sig = + v8::FunctionTemplate::New( + IncrementingSignatureCallback, Local<Value>(), sig); + v8::Handle<v8::FunctionTemplate> callback = + v8::FunctionTemplate::New(IncrementingSignatureCallback); v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(); sub_fun->Inherit(fun); - env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction()); - CompileRun( - "var o = new SubFun();" - "o.m();"); - CHECK_EQ(2, signature_callback_count); - - v8::TryCatch try_catch; - CompileRun( - "var o = { };" - "o.m = Fun.prototype.m;" - "o.m();"); - CHECK_EQ(2, signature_callback_count); - CHECK(try_catch.HasCaught()); - try_catch.Reset(); v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New(); - sub_fun->Inherit(fun); + // Install properties. + v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate(); + fun_proto->Set(v8_str("prop_sig"), callback_sig); + fun_proto->Set(v8_str("prop"), callback); + fun_proto->SetAccessorProperty( + v8_str("accessor_sig"), callback_sig, callback_sig); + fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback); + // Instantiate templates. + Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance(); + Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance(); + // Setup global variables. + env->Global()->Set(v8_str("Fun"), fun->GetFunction()); env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction()); + env->Global()->Set(v8_str("fun_instance"), fun_instance); + env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance); CompileRun( - "var o = new UnrelFun();" - "o.m = Fun.prototype.m;" - "o.m();"); - CHECK_EQ(2, signature_callback_count); - CHECK(try_catch.HasCaught()); + "var accessor_sig_key = 'accessor_sig';" + "var accessor_key = 'accessor';" + "var prop_sig_key = 'prop_sig';" + "var prop_key = 'prop';" + "" + "function copy_props(obj) {" + " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];" + " var source = Fun.prototype;" + " for (var i in keys) {" + " var key = keys[i];" + " var desc = Object.getOwnPropertyDescriptor(source, key);" + " Object.defineProperty(obj, key, desc);" + " }" + "}" + "" + "var obj = {};" + "copy_props(obj);" + "var unrel = new UnrelFun();" + "copy_props(unrel);"); + // Test with and without ICs + const char* test_objects[] = { + "fun_instance", "sub_fun_instance", "obj", "unrel" }; + unsigned bad_signature_start_offset = 2; + for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) { + i::ScopedVector<char> source(200); + i::OS::SNPrintF( + source, "var test_object = %s; test_object", test_objects[i]); + Local<Value> test_object = CompileRun(source.start()); + TestSignature("test_object.prop();", test_object); + TestSignature("test_object.accessor;", test_object); + TestSignature("test_object[accessor_key];", test_object); + TestSignature("test_object.accessor = 1;", test_object); + TestSignature("test_object[accessor_key] = 1;", test_object); + if (i >= bad_signature_start_offset) test_object = Local<Value>(); + TestSignature("test_object.prop_sig();", test_object); + TestSignature("test_object.accessor_sig;", test_object); + TestSignature("test_object[accessor_sig_key];", test_object); + TestSignature("test_object.accessor_sig = 1;", test_object); + TestSignature("test_object[accessor_sig_key] = 1;", test_object); + } } @@ -1360,7 +1430,7 @@ THREADED_TEST(BigSmiInteger) { int32_t value = i::Smi::kMaxValue; // We cannot add one to a Smi::kMaxValue without wrapping. - if (i::kSmiValueSize < 32) { + if (i::SmiValuesAre31Bits()) { CHECK(i::Smi::IsValid(value)); CHECK(!i::Smi::IsValid(value + 1)); @@ -1379,7 +1449,7 @@ THREADED_TEST(BigInteger) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); // We cannot add one to a Smi::kMaxValue without wrapping. - if (i::kSmiValueSize < 32) { + if (i::SmiValuesAre31Bits()) { // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1. // The code will not be run in that case, due to the "if" guard. int32_t value = @@ -1830,7 +1900,17 @@ void InterceptorGetter(Local<String> name, void InterceptorSetter(Local<String> name, Local<Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - // Intercept accesses that set certain integer values. + // Intercept accesses that set certain integer values, for which the name does + // not start with 'accessor_'. + String::Utf8Value utf8(name); + char* name_str = *utf8; + char prefix[] = "accessor_"; + int i; + for (i = 0; name_str[i] && prefix[i]; ++i) { + if (name_str[i] != prefix[i]) break; + } + if (!prefix[i]) return; + if (value->IsInt32() && value->Int32Value() < 10000) { Handle<Object> self = info.This(); self->SetHiddenValue(name, value); @@ -2682,9 +2762,6 @@ static void CheckInternalFieldsAreZero(v8::Handle<T> value) { THREADED_TEST(ArrayBuffer_ApiInternalToExternal) { - i::FLAG_harmony_array_buffer = true; - i::FLAG_harmony_typed_arrays = true; - LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope handle_scope(isolate); @@ -2721,9 +2798,6 @@ THREADED_TEST(ArrayBuffer_ApiInternalToExternal) { THREADED_TEST(ArrayBuffer_JSInternalToExternal) { - i::FLAG_harmony_array_buffer = true; - i::FLAG_harmony_typed_arrays = true; - LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope handle_scope(isolate); @@ -2766,9 +2840,6 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) { THREADED_TEST(ArrayBuffer_External) { - i::FLAG_harmony_array_buffer = true; - i::FLAG_harmony_typed_arrays = true; - LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope handle_scope(isolate); @@ -3119,7 +3190,7 @@ THREADED_TEST(ResettingGlobalHandle) { v8::HandleScope scope(isolate); CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6); } - global.Dispose(isolate); + global.Dispose(); CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1); } @@ -3175,19 +3246,52 @@ THREADED_TEST(GlobalHandleUpcast) { v8::HandleScope scope(isolate); v8::Local<String> local = v8::Local<String>::New(v8_str("str")); v8::Persistent<String> global_string(isolate, local); -#ifdef V8_USE_UNSAFE_HANDLES - v8::Persistent<Value> global_value = - v8::Persistent<Value>::Cast(global_string); -#else v8::Persistent<Value>& global_value = v8::Persistent<Value>::Cast(global_string); -#endif CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString()); CHECK(global_string == v8::Persistent<String>::Cast(global_value)); global_string.Dispose(); } +THREADED_TEST(HandleEquality) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Persistent<String> global1; + v8::Persistent<String> global2; + { + v8::HandleScope scope(isolate); + global1.Reset(isolate, v8_str("str")); + global2.Reset(isolate, v8_str("str2")); + } + CHECK_EQ(global1 == global1, true); + CHECK_EQ(global1 != global1, false); + { + v8::HandleScope scope(isolate); + Local<String> local1 = Local<String>::New(isolate, global1); + Local<String> local2 = Local<String>::New(isolate, global2); + + CHECK_EQ(global1 == local1, true); + CHECK_EQ(global1 != local1, false); + CHECK_EQ(local1 == global1, true); + CHECK_EQ(local1 != global1, false); + + CHECK_EQ(global1 == local2, false); + CHECK_EQ(global1 != local2, true); + CHECK_EQ(local2 == global1, false); + CHECK_EQ(local2 != global1, true); + + CHECK_EQ(local1 == local2, false); + CHECK_EQ(local1 != local2, true); + + Local<String> anotherLocal1 = Local<String>::New(isolate, global1); + CHECK_EQ(local1 == anotherLocal1, true); + CHECK_EQ(local1 != anotherLocal1, false); + } + global1.Dispose(); + global2.Dispose(); +} + + THREADED_TEST(LocalHandle) { v8::HandleScope scope(v8::Isolate::GetCurrent()); v8::Local<String> local = v8::Local<String>::New(v8_str("str")); @@ -3215,7 +3319,7 @@ static void WeakPointerCallback(v8::Isolate* isolate, WeakCallCounter* counter) { CHECK_EQ(1234, counter->id()); counter->increment(); - handle->Dispose(isolate); + handle->Dispose(); } @@ -3288,8 +3392,8 @@ THREADED_TEST(ApiObjectGroups) { root.MakeWeak(&counter, &WeakPointerCallback); // But make children strong roots---all the objects (except for children) // should be collectable now. - g1c1.ClearWeak(iso); - g2c1.ClearWeak(iso); + g1c1.ClearWeak(); + g2c1.ClearWeak(); // Groups are deleted, rebuild groups. { @@ -3339,29 +3443,29 @@ THREADED_TEST(ApiObjectGroupsCycle) { g1s2.Reset(iso, Object::New()); g1s1.MakeWeak(&counter, &WeakPointerCallback); g1s2.MakeWeak(&counter, &WeakPointerCallback); - CHECK(g1s1.IsWeak(iso)); - CHECK(g1s2.IsWeak(iso)); + CHECK(g1s1.IsWeak()); + CHECK(g1s2.IsWeak()); g2s1.Reset(iso, Object::New()); g2s2.Reset(iso, Object::New()); g2s1.MakeWeak(&counter, &WeakPointerCallback); g2s2.MakeWeak(&counter, &WeakPointerCallback); - CHECK(g2s1.IsWeak(iso)); - CHECK(g2s2.IsWeak(iso)); + CHECK(g2s1.IsWeak()); + CHECK(g2s2.IsWeak()); g3s1.Reset(iso, Object::New()); g3s2.Reset(iso, Object::New()); g3s1.MakeWeak(&counter, &WeakPointerCallback); g3s2.MakeWeak(&counter, &WeakPointerCallback); - CHECK(g3s1.IsWeak(iso)); - CHECK(g3s2.IsWeak(iso)); + CHECK(g3s1.IsWeak()); + CHECK(g3s2.IsWeak()); g4s1.Reset(iso, Object::New()); g4s2.Reset(iso, Object::New()); g4s1.MakeWeak(&counter, &WeakPointerCallback); g4s2.MakeWeak(&counter, &WeakPointerCallback); - CHECK(g4s1.IsWeak(iso)); - CHECK(g4s2.IsWeak(iso)); + CHECK(g4s1.IsWeak()); + CHECK(g4s2.IsWeak()); } Persistent<Value> root(iso, g1s1); // make a root. @@ -3463,19 +3567,19 @@ TEST(ApiObjectGroupsCycleForScavenger) { // Make a root. Persistent<Value> root(iso, g1s1); - root.MarkPartiallyDependent(iso); + root.MarkPartiallyDependent(); // Connect groups. We're building the following cycle: // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other // groups. { HandleScope handle_scope(iso); - g1s1.MarkPartiallyDependent(iso); - g1s2.MarkPartiallyDependent(iso); - g2s1.MarkPartiallyDependent(iso); - g2s2.MarkPartiallyDependent(iso); - g3s1.MarkPartiallyDependent(iso); - g3s2.MarkPartiallyDependent(iso); + g1s1.MarkPartiallyDependent(); + g1s2.MarkPartiallyDependent(); + g2s1.MarkPartiallyDependent(); + g2s2.MarkPartiallyDependent(); + g3s1.MarkPartiallyDependent(); + g3s2.MarkPartiallyDependent(); iso->SetObjectGroupId(g1s1, UniqueId(1)); iso->SetObjectGroupId(g1s2, UniqueId(1)); Local<Object>::New(iso, g1s1.As<Object>())->Set( @@ -3499,18 +3603,17 @@ TEST(ApiObjectGroupsCycleForScavenger) { // Weaken the root. root.MakeWeak(&counter, &WeakPointerCallback); - root.MarkPartiallyDependent(iso); + root.MarkPartiallyDependent(); - v8::Isolate* isolate = v8::Isolate::GetCurrent(); // Groups are deleted, rebuild groups. { HandleScope handle_scope(iso); - g1s1.MarkPartiallyDependent(isolate); - g1s2.MarkPartiallyDependent(isolate); - g2s1.MarkPartiallyDependent(isolate); - g2s2.MarkPartiallyDependent(isolate); - g3s1.MarkPartiallyDependent(isolate); - g3s2.MarkPartiallyDependent(isolate); + g1s1.MarkPartiallyDependent(); + g1s2.MarkPartiallyDependent(); + g2s1.MarkPartiallyDependent(); + g2s2.MarkPartiallyDependent(); + g3s1.MarkPartiallyDependent(); + g3s2.MarkPartiallyDependent(); iso->SetObjectGroupId(g1s1, UniqueId(1)); iso->SetObjectGroupId(g1s2, UniqueId(1)); Local<Object>::New(iso, g1s1.As<Object>())->Set( @@ -4868,7 +4971,7 @@ THREADED_TEST(Equality) { v8::Handle<v8::Object> obj = v8::Object::New(); v8::Persistent<v8::Object> alias(isolate, obj); CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj)); - alias.Dispose(isolate); + alias.Dispose(); } @@ -5183,7 +5286,7 @@ THREADED_TEST(SimplePropertyWrite) { CHECK(xValue.IsEmpty()); script->Run(); CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue)); - xValue.Dispose(context->GetIsolate()); + xValue.Dispose(); xValue.Clear(); } } @@ -5200,7 +5303,7 @@ THREADED_TEST(SetterOnly) { CHECK(xValue.IsEmpty()); script->Run(); CHECK_EQ(v8_num(4), Local<Value>::New(v8::Isolate::GetCurrent(), xValue)); - xValue.Dispose(context->GetIsolate()); + xValue.Dispose(); xValue.Clear(); } } @@ -6575,7 +6678,7 @@ class Snorkel { class Whammy { public: explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } - ~Whammy() { script_.Dispose(isolate_); } + ~Whammy() { script_.Dispose(); } v8::Handle<Script> getScript() { if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); return Local<Script>::New(isolate_, script_); @@ -6593,7 +6696,7 @@ static void HandleWeakReference(v8::Isolate* isolate, v8::Persistent<v8::Value>* obj, Snorkel* snorkel) { delete snorkel; - obj->ClearWeak(isolate); + obj->ClearWeak(); } void WhammyPropertyGetter(Local<String> name, @@ -6649,7 +6752,7 @@ THREADED_TEST(WeakReference) { static void DisposeAndSetFlag(v8::Isolate* isolate, v8::Persistent<v8::Object>* obj, bool* data) { - obj->Dispose(isolate); + obj->Dispose(); *(data) = true; } @@ -6672,10 +6775,10 @@ THREADED_TEST(IndependentWeakHandle) { bool object_b_disposed = false; object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag); object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag); - CHECK(!object_b.IsIndependent(iso)); - object_a.MarkIndependent(iso); - object_b.MarkIndependent(iso); - CHECK(object_b.IsIndependent(iso)); + CHECK(!object_b.IsIndependent()); + object_a.MarkIndependent(); + object_b.MarkIndependent(); + CHECK(object_b.IsIndependent()); HEAP->PerformScavenge(); CHECK(object_a_disposed); CHECK(object_b_disposed); @@ -6695,7 +6798,7 @@ static void InvokeMarkSweep() { static void ForceScavenge(v8::Isolate* isolate, v8::Persistent<v8::Object>* obj, bool* data) { - obj->Dispose(isolate); + obj->Dispose(); *(data) = true; InvokeScavenge(); } @@ -6704,7 +6807,7 @@ static void ForceScavenge(v8::Isolate* isolate, static void ForceMarkSweep(v8::Isolate* isolate, v8::Persistent<v8::Object>* obj, bool* data) { - obj->Dispose(isolate); + obj->Dispose(); *(data) = true; InvokeMarkSweep(); } @@ -6733,7 +6836,7 @@ THREADED_TEST(GCFromWeakCallbacks) { } bool disposed = false; object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]); - object.MarkIndependent(isolate); + object.MarkIndependent(); invoke_gc[outer_gc](); CHECK(disposed); } @@ -6744,7 +6847,7 @@ THREADED_TEST(GCFromWeakCallbacks) { static void RevivingCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* obj, bool* data) { - obj->ClearWeak(isolate); + obj->ClearWeak(); *(data) = true; } @@ -6766,7 +6869,7 @@ THREADED_TEST(IndependentHandleRevival) { } bool revived = false; object.MakeWeak(&revived, &RevivingCallback); - object.MarkIndependent(isolate); + object.MarkIndependent(); HEAP->PerformScavenge(); CHECK(revived); HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); @@ -8228,11 +8331,19 @@ static bool IndexedAccessBlocker(Local<v8::Object> global, } -static int g_echo_value = -1; +static int g_echo_value_1 = -1; +static int g_echo_value_2 = -1; + + static void EchoGetter( Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - info.GetReturnValue().Set(v8_num(g_echo_value)); + info.GetReturnValue().Set(v8_num(g_echo_value_1)); +} + + +static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + info.GetReturnValue().Set(v8_num(g_echo_value_2)); } @@ -8240,7 +8351,14 @@ static void EchoSetter(Local<String> name, Local<Value> value, const v8::PropertyCallbackInfo<void>&) { if (value->IsNumber()) - g_echo_value = value->Int32Value(); + g_echo_value_1 = value->Int32Value(); +} + + +static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Handle<v8::Value> value = info[0]; + if (value->IsNumber()) + g_echo_value_2 = value->Int32Value(); } @@ -8258,6 +8376,12 @@ static void UnreachableSetter(Local<String>, } +static void UnreachableFunction( + const v8::FunctionCallbackInfo<v8::Value>& info) { + CHECK(false); // This function should not be called.. +} + + TEST(AccessControl) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); @@ -8273,12 +8397,27 @@ TEST(AccessControl) { v8::Handle<Value>(), v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE)); + + global_template->SetAccessorProperty( + v8_str("accessible_js_prop"), + v8::FunctionTemplate::New(EchoGetter), + v8::FunctionTemplate::New(EchoSetter), + v8::None, + 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, v8::Handle<Value>(), v8::DEFAULT); + global_template->SetAccessorProperty( + v8_str("blocked_js_prop"), + v8::FunctionTemplate::New(UnreachableFunction), + v8::FunctionTemplate::New(UnreachableFunction), + v8::None, + v8::DEFAULT); + // Create an environment v8::Local<Context> context0 = Context::New(isolate, NULL, global_template); context0->Enter(); @@ -8471,26 +8610,47 @@ TEST(AccessControl) { value = CompileRun("other.accessible_prop = 3"); CHECK(value->IsNumber()); CHECK_EQ(3, value->Int32Value()); - CHECK_EQ(3, g_echo_value); + CHECK_EQ(3, g_echo_value_1); + + // Access accessible js property + value = CompileRun("other.accessible_js_prop = 3"); + CHECK(value->IsNumber()); + CHECK_EQ(3, value->Int32Value()); + CHECK_EQ(3, g_echo_value_2); value = CompileRun("other.accessible_prop"); CHECK(value->IsNumber()); CHECK_EQ(3, value->Int32Value()); + value = CompileRun("other.accessible_js_prop"); + CHECK(value->IsNumber()); + CHECK_EQ(3, value->Int32Value()); + value = CompileRun( "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value"); CHECK(value->IsNumber()); CHECK_EQ(3, value->Int32Value()); + value = CompileRun( + "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()"); + CHECK(value->IsNumber()); + CHECK_EQ(3, value->Int32Value()); + value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')"); CHECK(value->IsTrue()); + value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')"); + CHECK(value->IsTrue()); + // Enumeration doesn't enumerate accessors from inaccessible objects in // the prototype chain even if the accessors are in themselves accessible. value = CompileRun("(function(){var obj = {'__proto__':other};" "for (var p in obj)" - " if (p == 'accessible_prop' || p == 'blocked_prop') {" + " if (p == 'accessible_prop' ||" + " p == 'accessible_js_prop' ||" + " p == 'blocked_js_prop' ||" + " p == 'blocked_js_prop') {" " return false;" " }" "return true;})()"); @@ -8562,7 +8722,7 @@ TEST(AccessControlES5) { // Make sure that we can set the accessible accessors value using normal // assignment. CompileRun("other.accessible_prop = 42"); - CHECK_EQ(42, g_echo_value); + CHECK_EQ(42, g_echo_value_1); v8::Handle<Value> value; // We follow Safari in ignoring assignments to host object accessors. @@ -9522,6 +9682,26 @@ THREADED_TEST(SetPrototypeThrows) { } +THREADED_TEST(FunctionRemovePrototype) { + LocalContext context; + v8::HandleScope handle_scope(context->GetIsolate()); + + Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(); + t1->RemovePrototype(); + Local<v8::Function> fun = t1->GetFunction(); + context->Global()->Set(v8_str("fun"), fun); + CHECK(!CompileRun("'prototype' in fun")->BooleanValue()); + + v8::TryCatch try_catch; + CompileRun("new fun()"); + CHECK(try_catch.HasCaught()); + + try_catch.Reset(); + fun->NewInstance(); + CHECK(try_catch.HasCaught()); +} + + THREADED_TEST(GetterSetterExceptions) { LocalContext context; v8::HandleScope handle_scope(context->GetIsolate()); @@ -12133,8 +12313,7 @@ THREADED_TEST(ObjectGetConstructorName) { bool ApiTestFuzzer::fuzzing_ = false; -i::Semaphore* ApiTestFuzzer::all_tests_done_= - i::OS::CreateSemaphore(0); +i::Semaphore ApiTestFuzzer::all_tests_done_(0); int ApiTestFuzzer::active_tests_; int ApiTestFuzzer::tests_being_run_; int ApiTestFuzzer::current_; @@ -12165,14 +12344,14 @@ bool ApiTestFuzzer::NextThread() { RegisterThreadedTest::nth(test_position)->name()); } current_ = test_position; - RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal(); + RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal(); return true; } void ApiTestFuzzer::Run() { // When it is our turn... - gate_->Wait(); + gate_.Wait(); { // ... get the V8 lock and start running the test. v8::Locker locker(CcTest::default_isolate()); @@ -12183,7 +12362,7 @@ void ApiTestFuzzer::Run() { active_tests_--; // If it was the last then signal that fact. if (active_tests_ == 0) { - all_tests_done_->Signal(); + all_tests_done_.Signal(); } else { // Otherwise select a new test and start that. NextThread(); @@ -12220,7 +12399,7 @@ void ApiTestFuzzer::RunAllTests() { current_ = -1; NextThread(); // Wait till they are all done. - all_tests_done_->Wait(); + all_tests_done_.Wait(); } @@ -12241,7 +12420,7 @@ void ApiTestFuzzer::ContextSwitch() { // Now it can start. v8::Unlocker unlocker(CcTest::default_isolate()); // Wait till someone starts us again. - gate_->Wait(); + gate_.Wait(); // And we're off. } } @@ -12258,9 +12437,6 @@ void ApiTestFuzzer::TearDown() { // Lets not be needlessly self-referential. TEST(Threading1) { - // TODO(mstarzinger): Disabled in GC stress mode for now, we should find the - // correct timeout for this an re-enable this test again - if (i::FLAG_stress_compaction) return; ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); @@ -12489,6 +12665,75 @@ TEST(DontLeakGlobalObjects) { } } +template<class T> +struct CopyablePersistentTraits { + typedef Persistent<T, CopyablePersistentTraits<T> > CopyablePersistent; + static const bool kResetInDestructor = true; + template<class S, class M> + static V8_INLINE void Copy(const Persistent<S, M>& source, + CopyablePersistent* dest) { + // do nothing, just allow copy + } +}; + + +TEST(CopyablePersistent) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + i::GlobalHandles* globals = + reinterpret_cast<i::Isolate*>(isolate)->global_handles(); + int initial_handles = globals->global_handles_count(); + { + v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> > handle1; + { + v8::HandleScope scope(isolate); + handle1.Reset(isolate, v8::Object::New()); + } + CHECK_EQ(initial_handles + 1, globals->global_handles_count()); + v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> > handle2; + handle2 = handle1; + CHECK(handle1 == handle2); + CHECK_EQ(initial_handles + 2, globals->global_handles_count()); + v8::Persistent<v8::Object, CopyablePersistentTraits<v8::Object> > + handle3(handle2); + CHECK(handle1 == handle3); + CHECK_EQ(initial_handles + 3, globals->global_handles_count()); + } + // Verify autodispose + CHECK_EQ(initial_handles, globals->global_handles_count()); +} + + +static void WeakApiCallback( + const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) { + Local<Value> value = data.GetValue()->Get(v8_str("key")); + CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value())); + data.GetParameter()->Reset(); + delete data.GetParameter(); +} + + +TEST(WeakCallbackApi) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + i::GlobalHandles* globals = + reinterpret_cast<i::Isolate*>(isolate)->global_handles(); + int initial_handles = globals->global_handles_count(); + { + v8::HandleScope scope(isolate); + v8::Local<v8::Object> obj = v8::Object::New(); + obj->Set(v8_str("key"), v8::Integer::New(231, isolate)); + v8::Persistent<v8::Object>* handle = + new v8::Persistent<v8::Object>(isolate, obj); + handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle, + WeakApiCallback); + } + reinterpret_cast<i::Isolate*>(isolate)->heap()-> + CollectAllGarbage(i::Heap::kNoGCFlags); + // Verify disposed. + CHECK_EQ(initial_handles, globals->global_handles_count()); +} + v8::Persistent<v8::Object> some_object; v8::Persistent<v8::Object> bad_handle; @@ -12498,7 +12743,7 @@ void NewPersistentHandleCallback(v8::Isolate* isolate, void*) { v8::HandleScope scope(isolate); bad_handle.Reset(isolate, some_object); - handle->Dispose(isolate); + handle->Dispose(); } @@ -12518,7 +12763,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) { // in reverse allocation order, so if second allocated handle is deleted, // weak callback of the first handle would be able to 'reallocate' it. handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback); - handle2.Dispose(isolate); + handle2.Dispose(); HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -12528,9 +12773,9 @@ v8::Persistent<v8::Object> to_be_disposed; void DisposeAndForceGcCallback(v8::Isolate* isolate, v8::Persistent<v8::Value>* handle, void*) { - to_be_disposed.Dispose(isolate); + to_be_disposed.Dispose(); HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); - handle->Dispose(isolate); + handle->Dispose(); } @@ -12552,7 +12797,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { void DisposingCallback(v8::Isolate* isolate, v8::Persistent<v8::Value>* handle, void*) { - handle->Dispose(isolate); + handle->Dispose(); } void HandleCreatingCallback(v8::Isolate* isolate, @@ -12560,7 +12805,7 @@ void HandleCreatingCallback(v8::Isolate* isolate, void*) { v8::HandleScope scope(isolate); v8::Persistent<v8::Object>(isolate, v8::Object::New()); - handle->Dispose(isolate); + handle->Dispose(); } @@ -12958,9 +13203,6 @@ TEST(SetFunctionEntryHook) { // Experimental natives are compiled during snapshot deserialization. // This test breaks because InstallGetter (function from snapshot that // only gets called from experimental natives) is compiled with entry hooks. - i::FLAG_harmony_typed_arrays = false; - i::FLAG_harmony_array_buffer = false; - i::FLAG_allow_natives_syntax = true; i::FLAG_use_inlining = false; @@ -13159,7 +13401,7 @@ TEST(SetJitCodeEventHandler) { v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code()); // Clear the compilation cache to get more wastage. - ISOLATE->compilation_cache()->Clear(); + reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear(); } // Force code movement. @@ -13963,10 +14205,9 @@ THREADED_TEST(CrossContextNew) { class RegExpInterruptTest { public: - RegExpInterruptTest() : block_(NULL) {} - ~RegExpInterruptTest() { delete block_; } + RegExpInterruptTest() : block_(0) {} + ~RegExpInterruptTest() {} void RunTest() { - block_ = i::OS::CreateSemaphore(0); gc_count_ = 0; gc_during_regexp_ = 0; regexp_success_ = false; @@ -14001,7 +14242,7 @@ class RegExpInterruptTest { }; void CollectGarbage() { - block_->Wait(); + block_.Wait(); while (gc_during_regexp_ < kRequiredGCs) { { v8::Locker lock(CcTest::default_isolate()); @@ -14015,7 +14256,7 @@ class RegExpInterruptTest { } void LongRunningRegExp() { - block_->Signal(); // Enable garbage collection thread on next preemption. + block_.Signal(); // Enable garbage collection thread on next preemption. int rounds = 0; while (gc_during_regexp_ < kRequiredGCs) { int gc_before = gc_count_; @@ -14053,7 +14294,7 @@ class RegExpInterruptTest { regexp_success_ = true; } - i::Semaphore* block_; + i::Semaphore block_; int gc_count_; int gc_during_regexp_; bool regexp_success_; @@ -14086,10 +14327,9 @@ TEST(RegExpInterruption) { class ApplyInterruptTest { public: - ApplyInterruptTest() : block_(NULL) {} - ~ApplyInterruptTest() { delete block_; } + ApplyInterruptTest() : block_(0) {} + ~ApplyInterruptTest() {} void RunTest() { - block_ = i::OS::CreateSemaphore(0); gc_count_ = 0; gc_during_apply_ = 0; apply_success_ = false; @@ -14124,7 +14364,7 @@ class ApplyInterruptTest { }; void CollectGarbage() { - block_->Wait(); + block_.Wait(); while (gc_during_apply_ < kRequiredGCs) { { v8::Locker lock(CcTest::default_isolate()); @@ -14137,7 +14377,7 @@ class ApplyInterruptTest { } void LongRunningApply() { - block_->Signal(); + block_.Signal(); int rounds = 0; while (gc_during_apply_ < kRequiredGCs) { int gc_before = gc_count_; @@ -14162,7 +14402,7 @@ class ApplyInterruptTest { apply_success_ = true; } - i::Semaphore* block_; + i::Semaphore block_; int gc_count_; int gc_during_apply_; bool apply_success_; @@ -14375,12 +14615,12 @@ TEST(CompileExternalTwoByteSource) { class RegExpStringModificationTest { public: RegExpStringModificationTest() - : block_(i::OS::CreateSemaphore(0)), + : block_(0), morphs_(0), morphs_during_regexp_(0), ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)), uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {} - ~RegExpStringModificationTest() { delete block_; } + ~RegExpStringModificationTest() {} void RunTest() { i::Factory* factory = i::Isolate::Current()->factory(); @@ -14437,7 +14677,7 @@ class RegExpStringModificationTest { }; void MorphString() { - block_->Wait(); + block_.Wait(); while (morphs_during_regexp_ < kRequiredModifications && morphs_ < kMaxModifications) { { @@ -14453,7 +14693,7 @@ class RegExpStringModificationTest { } void LongRunningRegExp() { - block_->Signal(); // Enable morphing thread on next preemption. + block_.Signal(); // Enable morphing thread on next preemption. while (morphs_during_regexp_ < kRequiredModifications && morphs_ < kMaxModifications) { int morphs_before = morphs_; @@ -14475,7 +14715,7 @@ class RegExpStringModificationTest { } i::uc16 two_byte_content_[15]; - i::Semaphore* block_; + i::Semaphore block_; int morphs_; int morphs_during_regexp_; bool regexp_success_; @@ -14902,10 +15142,19 @@ THREADED_TEST(Regress16276) { CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value()); } +static void CheckElementValue(i::Isolate* isolate, + int expected, + i::Handle<i::Object> obj, + int offset) { + i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked(); + CHECK_EQ(expected, i::Smi::cast(element)->value()); +} + THREADED_TEST(PixelArray) { LocalContext context; - i::Factory* factory = i::Isolate::Current()->factory(); + i::Isolate* isolate = i::Isolate::Current(); + i::Factory* factory = isolate->factory(); v8::HandleScope scope(context->GetIsolate()); const int kElementCount = 260; uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); @@ -14931,7 +15180,7 @@ THREADED_TEST(PixelArray) { // Set the elements to be the pixels. // jsobj->set_elements(*pixels); obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); - CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CheckElementValue(isolate, 1, jsobj, 1); obj->Set(v8_str("field"), v8::Int32::New(1503)); context->Global()->Set(v8_str("pixels"), obj); v8::Handle<v8::Value> result = CompileRun("pixels.field"); @@ -14988,40 +15237,33 @@ THREADED_TEST(PixelArray) { i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CheckElementValue(isolate, 2, jsobj, 1); *value.location() = i::Smi::FromInt(256); no_failure = i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); - CHECK_EQ(255, - i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CheckElementValue(isolate, 255, jsobj, 1); *value.location() = i::Smi::FromInt(-1); no_failure = i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 1); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[i] = (i * 65) - 109;" "}" "pixels[1] + pixels[6];"); CHECK_EQ(255, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); - CHECK_EQ(21, - i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value()); - CHECK_EQ(86, - i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value()); - CHECK_EQ(151, - i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value()); - CHECK_EQ(216, - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); - CHECK_EQ(255, - i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value()); - CHECK_EQ(255, - i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 0); + CheckElementValue(isolate, 0, jsobj, 1); + CheckElementValue(isolate, 21, jsobj, 2); + CheckElementValue(isolate, 86, jsobj, 3); + CheckElementValue(isolate, 151, jsobj, 4); + CheckElementValue(isolate, 216, jsobj, 5); + CheckElementValue(isolate, 255, jsobj, 6); + CheckElementValue(isolate, 255, jsobj, 7); result = CompileRun("var sum = 0;" "for (var i = 0; i < 8; i++) {" " sum += pixels[i];" @@ -15034,50 +15276,49 @@ THREADED_TEST(PixelArray) { "}" "pixels[1] + pixels[6];"); CHECK_EQ(8, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value()); - CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value()); - CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value()); - CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value()); - CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); - CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value()); - CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 0); + CheckElementValue(isolate, 1, jsobj, 1); + CheckElementValue(isolate, 2, jsobj, 2); + CheckElementValue(isolate, 3, jsobj, 3); + CheckElementValue(isolate, 4, jsobj, 4); + CheckElementValue(isolate, 6, jsobj, 5); + CheckElementValue(isolate, 7, jsobj, 6); + CheckElementValue(isolate, 8, jsobj, 7); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[7] = undefined;" "}" "pixels[7];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 7); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[6] = '2.3';" "}" "pixels[6];"); CHECK_EQ(2, result->Int32Value()); - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value()); + CheckElementValue(isolate, 2, jsobj, 6); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[5] = NaN;" "}" "pixels[5];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 5); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[8] = Infinity;" "}" "pixels[8];"); CHECK_EQ(255, result->Int32Value()); - CHECK_EQ(255, - i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value()); + CheckElementValue(isolate, 255, jsobj, 8); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[9] = -Infinity;" "}" "pixels[9];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 9); result = CompileRun("pixels[3] = 33;" "delete pixels[3];" @@ -15394,6 +15635,7 @@ static void ObjectWithExternalArrayTestHelper( v8::ExternalArrayType array_type, int64_t low, int64_t high) { i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); + i::Isolate* isolate = jsobj->GetIsolate(); obj->Set(v8_str("field"), v8::Int32::New(1503)); context->Global()->Set(v8_str("ext_array"), obj); v8::Handle<v8::Value> result = CompileRun("ext_array.field"); @@ -15535,12 +15777,11 @@ static void ObjectWithExternalArrayTestHelper( CHECK_EQ(0, result->Int32Value()); if (array_type == v8::kExternalDoubleArray || array_type == v8::kExternalFloatArray) { - CHECK_EQ( - static_cast<int>(i::OS::nan_value()), - static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number())); + CHECK_EQ(static_cast<int>(i::OS::nan_value()), + static_cast<int>( + jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number())); } else { - CHECK_EQ(0, static_cast<int>( - jsobj->GetElement(7)->ToObjectChecked()->Number())); + CheckElementValue(isolate, 0, jsobj, 7); } result = CompileRun("for (var i = 0; i < 8; i++) {" @@ -15548,8 +15789,9 @@ static void ObjectWithExternalArrayTestHelper( "}" "ext_array[6];"); CHECK_EQ(2, result->Int32Value()); - CHECK_EQ( - 2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number())); + CHECK_EQ(2, + static_cast<int>( + jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number())); if (array_type != v8::kExternalFloatArray && array_type != v8::kExternalDoubleArray) { @@ -15563,8 +15805,7 @@ static void ObjectWithExternalArrayTestHelper( "}" "ext_array[5];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 5); result = CompileRun("for (var i = 0; i < 8; i++) {" " ext_array[i] = 5;" @@ -15576,8 +15817,7 @@ static void ObjectWithExternalArrayTestHelper( 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()); + CheckElementValue(isolate, expected_value, jsobj, 5); result = CompileRun("for (var i = 0; i < 8; i++) {" " ext_array[i] = 5;" @@ -15587,8 +15827,7 @@ static void ObjectWithExternalArrayTestHelper( "}" "ext_array[5];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ(0, - i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); + CheckElementValue(isolate, 0, jsobj, 5); // Check truncation behavior of integral arrays. const char* unsigned_data = @@ -15694,7 +15933,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, int64_t low, int64_t high) { LocalContext context; - i::Factory* factory = i::Isolate::Current()->factory(); + i::Isolate* isolate = i::Isolate::Current(); + i::Factory* factory = isolate->factory(); v8::HandleScope scope(context->GetIsolate()); const int kElementCount = 40; int element_size = ExternalArrayElementSize(array_type); @@ -15722,8 +15962,9 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, obj->SetIndexedPropertiesToExternalArrayData(array_data, array_type, kElementCount); - CHECK_EQ( - 1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number())); + CHECK_EQ(1, + static_cast<int>( + jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number())); ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>( context.local(), obj, kElementCount, array_type, low, high); @@ -16157,8 +16398,6 @@ THREADED_TEST(DataView) { #define IS_ARRAY_BUFFER_VIEW_TEST(View) \ THREADED_TEST(Is##View) { \ - i::FLAG_harmony_array_buffer = true; \ - i::FLAG_harmony_typed_arrays = true; \ LocalContext env; \ v8::Isolate* isolate = env->GetIsolate(); \ v8::HandleScope handle_scope(isolate); \ @@ -16569,6 +16808,42 @@ TEST(SourceURLInStackTrace) { } +static int scriptIdInStack[2]; + +void AnalyzeScriptIdInStack( + const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::HandleScope scope(args.GetIsolate()); + v8::Handle<v8::StackTrace> stackTrace = + v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kScriptId); + CHECK_EQ(2, stackTrace->GetFrameCount()); + for (int i = 0; i < 2; i++) { + scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId(); + } +} + + +TEST(ScriptIdInStackTrace) { + v8::HandleScope scope(v8::Isolate::GetCurrent()); + Local<ObjectTemplate> templ = ObjectTemplate::New(); + templ->Set(v8_str("AnalyzeScriptIdInStack"), + v8::FunctionTemplate::New(AnalyzeScriptIdInStack)); + LocalContext context(0, templ); + + v8::Handle<v8::String> scriptSource = v8::String::New( + "function foo() {\n" + " AnalyzeScriptIdInStack();" + "}\n" + "foo();\n"); + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test")); + v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin)); + script->Run(); + for (int i = 0; i < 2; i++) { + CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo); + CHECK_EQ(scriptIdInStack[i], script->GetId()); + } +} + + void AnalyzeStackOfInlineScriptWithSourceURL( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::HandleScope scope(args.GetIsolate()); @@ -18461,15 +18736,15 @@ TEST(PersistentHandleVisitor) { v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); v8::Persistent<v8::Object> object(isolate, v8::Object::New()); - CHECK_EQ(0, object.WrapperClassId(isolate)); - object.SetWrapperClassId(isolate, 42); - CHECK_EQ(42, object.WrapperClassId(isolate)); + CHECK_EQ(0, object.WrapperClassId()); + object.SetWrapperClassId(42); + CHECK_EQ(42, object.WrapperClassId()); Visitor42 visitor(&object); v8::V8::VisitHandlesWithClassIds(&visitor); CHECK_EQ(1, visitor.counter_); - object.Dispose(isolate); + object.Dispose(); } @@ -18478,10 +18753,10 @@ TEST(WrapperClassId) { v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); v8::Persistent<v8::Object> object(isolate, v8::Object::New()); - CHECK_EQ(0, object.WrapperClassId(isolate)); - object.SetWrapperClassId(isolate, 65535); - CHECK_EQ(65535, object.WrapperClassId(isolate)); - object.Dispose(isolate); + CHECK_EQ(0, object.WrapperClassId()); + object.SetWrapperClassId(65535); + CHECK_EQ(65535, object.WrapperClassId()); + object.Dispose(); } @@ -18490,23 +18765,23 @@ TEST(PersistentHandleInNewSpaceVisitor) { v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); v8::Persistent<v8::Object> object1(isolate, v8::Object::New()); - CHECK_EQ(0, object1.WrapperClassId(isolate)); - object1.SetWrapperClassId(isolate, 42); - CHECK_EQ(42, object1.WrapperClassId(isolate)); + CHECK_EQ(0, object1.WrapperClassId()); + object1.SetWrapperClassId(42); + CHECK_EQ(42, object1.WrapperClassId()); HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); v8::Persistent<v8::Object> object2(isolate, v8::Object::New()); - CHECK_EQ(0, object2.WrapperClassId(isolate)); - object2.SetWrapperClassId(isolate, 42); - CHECK_EQ(42, object2.WrapperClassId(isolate)); + CHECK_EQ(0, object2.WrapperClassId()); + object2.SetWrapperClassId(42); + CHECK_EQ(42, object2.WrapperClassId()); Visitor42 visitor(&object2); v8::V8::VisitHandlesForPartialDependence(isolate, &visitor); CHECK_EQ(1, visitor.counter_); - object1.Dispose(isolate); - object2.Dispose(isolate); + object1.Dispose(); + object2.Dispose(); } @@ -19460,19 +19735,20 @@ TEST(StaticGetters) { TEST(IsolateEmbedderData) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); CHECK_EQ(NULL, isolate->GetData()); - CHECK_EQ(NULL, ISOLATE->GetData()); + CHECK_EQ(NULL, i_isolate->GetData()); static void* data1 = reinterpret_cast<void*>(0xacce55ed); isolate->SetData(data1); CHECK_EQ(data1, isolate->GetData()); - CHECK_EQ(data1, ISOLATE->GetData()); + CHECK_EQ(data1, i_isolate->GetData()); static void* data2 = reinterpret_cast<void*>(0xdecea5ed); - ISOLATE->SetData(data2); + i_isolate->SetData(data2); CHECK_EQ(data2, isolate->GetData()); - CHECK_EQ(data2, ISOLATE->GetData()); - ISOLATE->TearDown(); + CHECK_EQ(data2, i_isolate->GetData()); + i_isolate->TearDown(); CHECK_EQ(data2, isolate->GetData()); - CHECK_EQ(data2, ISOLATE->GetData()); + CHECK_EQ(data2, i_isolate->GetData()); } @@ -19935,19 +20211,17 @@ THREADED_TEST(JSONParseNumber) { } -#ifndef WIN32 +#if V8_OS_POSIX class ThreadInterruptTest { public: - ThreadInterruptTest() : sem_(NULL), sem_value_(0) { } - ~ThreadInterruptTest() { delete sem_; } + ThreadInterruptTest() : sem_(0), sem_value_(0) { } + ~ThreadInterruptTest() {} void RunTest() { - sem_ = i::OS::CreateSemaphore(0); - InterruptThread i_thread(this); i_thread.Start(); - sem_->Wait(); + sem_.Wait(); CHECK_EQ(kExpectedValue, sem_value_); } @@ -19978,7 +20252,7 @@ class ThreadInterruptTest { // Set value and signal semaphore test_->sem_value_ = 1; - test_->sem_->Signal(); + test_->sem_.Signal(); } static void SignalHandler(int signal) { @@ -19988,7 +20262,7 @@ class ThreadInterruptTest { ThreadInterruptTest* test_; }; - i::Semaphore* sem_; + i::Semaphore sem_; volatile int sem_value_; }; @@ -20171,6 +20445,10 @@ TEST(AccessCheckThrows) { CheckCorrectThrow("%GetLocalPropertyNames(other, true)"); CheckCorrectThrow("%DefineOrRedefineAccessorProperty(" "other, 'x', null, null, 1)"); + + // Reset the failed access check callback so it does not influence + // the other tests. + v8::V8::SetFailedAccessCheckCallbackFunction(NULL); } @@ -20190,4 +20468,122 @@ THREADED_TEST(Regress256330) { } -#endif // WIN32 +THREADED_TEST(CrankshaftInterceptorSetter) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope(v8::Isolate::GetCurrent()); + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + // Initialize fields to avoid transitions later. + "obj.age = 0;" + "obj.accessor_age = 42;" + "function setter(i) { this.accessor_age = i; };" + "function getter() { return this.accessor_age; };" + "function setAge(i) { obj.age = i; };" + "Object.defineProperty(obj, 'age', { get:getter, set:setter });" + "setAge(1);" + "setAge(2);" + "setAge(3);" + "%OptimizeFunctionOnNextCall(setAge);" + "setAge(4);"); + // All stores went through the interceptor. + ExpectInt32("obj.interceptor_age", 4); + ExpectInt32("obj.accessor_age", 42); +} + + +THREADED_TEST(CrankshaftInterceptorGetter) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope(v8::Isolate::GetCurrent()); + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + // Initialize fields to avoid transitions later. + "obj.age = 1;" + "obj.accessor_age = 42;" + "function getter() { return this.accessor_age; };" + "function getAge() { return obj.interceptor_age; };" + "Object.defineProperty(obj, 'interceptor_age', { get:getter });" + "getAge();" + "getAge();" + "getAge();" + "%OptimizeFunctionOnNextCall(getAge);"); + // Access through interceptor. + ExpectInt32("getAge()", 1); +} + + +THREADED_TEST(CrankshaftInterceptorFieldRead) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope(v8::Isolate::GetCurrent()); + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "obj.__proto__.interceptor_age = 42;" + "obj.age = 100;" + "function getAge() { return obj.interceptor_age; };"); + ExpectInt32("getAge();", 100); + ExpectInt32("getAge();", 100); + ExpectInt32("getAge();", 100); + CompileRun("%OptimizeFunctionOnNextCall(getAge);"); + // Access through interceptor. + ExpectInt32("getAge();", 100); +} + + +THREADED_TEST(CrankshaftInterceptorFieldWrite) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope(v8::Isolate::GetCurrent()); + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "obj.age = 100000;" + "function setAge(i) { obj.age = i };" + "setAge(100);" + "setAge(101);" + "setAge(102);" + "%OptimizeFunctionOnNextCall(setAge);" + "setAge(103);"); + ExpectInt32("obj.age", 100000); + ExpectInt32("obj.interceptor_age", 103); +} + + +#endif // V8_OS_POSIX + + +static Local<Value> function_new_expected_env; +static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) { + CHECK_EQ(function_new_expected_env, info.Data()); + info.GetReturnValue().Set(17); +} + + +THREADED_TEST(FunctionNew) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + Local<Object> data = v8::Object::New(); + function_new_expected_env = data; + Local<Function> func = Function::New(isolate, FunctionNewCallback, data); + env->Global()->Set(v8_str("func"), func); + Local<Value> result = CompileRun("func();"); + CHECK_EQ(v8::Integer::New(17, isolate), result); + // Verify function not cached + int serial_number = + i::Smi::cast(v8::Utils::OpenHandle(*func) + ->shared()->get_api_func_data()->serial_number())->value(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + i::Object* elm = i_isolate->native_context()->function_cache() + ->GetElementNoExceptionThrown(i_isolate, serial_number); + CHECK(elm->IsNull()); +} + diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index cac162e018..1a4c1ae369 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -1439,4 +1439,75 @@ TEST(17) { } +TEST(code_relative_offset) { + // Test extracting the offset of a label from the beginning of the code + // in a register. + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + HandleScope scope(isolate); + // Initialize a code object that will contain the code. + Handle<Object> code_object(isolate->heap()->undefined_value(), isolate); + + Assembler assm(isolate, NULL, 0); + + Label start, target_away, target_faraway; + + __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); + + // r3 is used as the address zero, the test will crash when we load it. + __ mov(r3, Operand::Zero()); + + // r5 will be a pointer to the start of the code. + __ mov(r5, Operand(code_object)); + __ mov_label_offset(r4, &start); + + __ mov_label_offset(r1, &target_faraway); + __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex)); + + __ mov_label_offset(r1, &target_away); + + // Jump straight to 'target_away' the first time and use the relative + // position the second time. This covers the case when extracting the + // position of a label which is linked. + __ mov(r2, Operand::Zero()); + __ bind(&start); + __ cmp(r2, Operand::Zero()); + __ b(eq, &target_away); + __ add(pc, r5, r1); + // Emit invalid instructions to push the label between 2^8 and 2^16 + // instructions away. The test will crash if they are reached. + for (int i = 0; i < (1 << 10); i++) { + __ ldr(r3, MemOperand(r3)); + } + __ bind(&target_away); + // This will be hit twice: r0 = r0 + 5 + 5. + __ add(r0, r0, Operand(5)); + + __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne); + __ add(pc, r5, r4, LeaveCC, ne); + + __ mov(r2, Operand(1)); + __ b(&start); + // Emit invalid instructions to push the label between 2^16 and 2^24 + // instructions away. The test will crash if they are reached. + for (int i = 0; i < (1 << 21); i++) { + __ ldr(r3, MemOperand(r3)); + } + __ bind(&target_faraway); + // r0 = r0 + 5 + 5 + 11 + __ add(r0, r0, Operand(11)); + + __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode(desc, + Code::ComputeFlags(Code::STUB), code_object); + CHECK(code->IsCode()); + F1 f = FUNCTION_CAST<F1>(code->entry()); + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0)); + ::printf("f() = %d\n", res); + CHECK_EQ(42, res); +} + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc index d5aaf4f212..f7d2311192 100644 --- a/deps/v8/test/cctest/test-assembler-x64.cc +++ b/deps/v8/test/cctest/test-assembler-x64.cc @@ -90,7 +90,6 @@ 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, @@ -113,7 +112,6 @@ 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, @@ -146,7 +144,6 @@ 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, @@ -169,7 +166,6 @@ 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, @@ -198,7 +194,6 @@ 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, @@ -233,7 +228,6 @@ 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, @@ -263,7 +257,6 @@ 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, diff --git a/deps/v8/test/cctest/test-circular-queue.cc b/deps/v8/test/cctest/test-circular-queue.cc index 4d7856e276..c900be1a64 100644 --- a/deps/v8/test/cctest/test-circular-queue.cc +++ b/deps/v8/test/cctest/test-circular-queue.cc @@ -35,77 +35,76 @@ using i::SamplingCircularQueue; TEST(SamplingCircularQueue) { - typedef SamplingCircularQueue::Cell Record; - const int kRecordsPerChunk = 4; - SamplingCircularQueue scq(sizeof(Record), - kRecordsPerChunk * sizeof(Record), - 3); + typedef i::AtomicWord Record; + const int kMaxRecordsInQueue = 4; + SamplingCircularQueue<Record, kMaxRecordsInQueue> scq; // Check that we are using non-reserved values. // Fill up the first chunk. - CHECK_EQ(NULL, scq.StartDequeue()); - for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.Enqueue()); + CHECK_EQ(NULL, scq.Peek()); + for (Record i = 1; i < 1 + kMaxRecordsInQueue; ++i) { + Record* rec = reinterpret_cast<Record*>(scq.StartEnqueue()); CHECK_NE(NULL, rec); *rec = i; - CHECK_EQ(NULL, scq.StartDequeue()); + scq.FinishEnqueue(); } - // Fill up the second chunk. Consumption must still be unavailable. - CHECK_EQ(NULL, scq.StartDequeue()); - for (Record i = 10; i < 10 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.Enqueue()); + // The queue is full, enqueue is not allowed. + CHECK_EQ(NULL, scq.StartEnqueue()); + + // Try to enqueue when the the queue is full. Consumption must be available. + CHECK_NE(NULL, scq.Peek()); + for (int i = 0; i < 10; ++i) { + Record* rec = reinterpret_cast<Record*>(scq.StartEnqueue()); + CHECK_EQ(NULL, rec); + CHECK_NE(NULL, scq.Peek()); + } + + // Consume all records. + for (Record i = 1; i < 1 + kMaxRecordsInQueue; ++i) { + Record* rec = reinterpret_cast<Record*>(scq.Peek()); CHECK_NE(NULL, rec); - *rec = i; - CHECK_EQ(NULL, scq.StartDequeue()); + CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); + CHECK_EQ(rec, reinterpret_cast<Record*>(scq.Peek())); + scq.Remove(); + CHECK_NE(rec, reinterpret_cast<Record*>(scq.Peek())); } + // The queue is empty. + CHECK_EQ(NULL, scq.Peek()); - Record* rec = reinterpret_cast<Record*>(scq.Enqueue()); - CHECK_NE(NULL, rec); - *rec = 20; - // Now as we started filling up the third chunk, consumption - // must become possible. - CHECK_NE(NULL, scq.StartDequeue()); - // Consume the first chunk. - for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); + CHECK_EQ(NULL, scq.Peek()); + for (Record i = 0; i < kMaxRecordsInQueue / 2; ++i) { + Record* rec = reinterpret_cast<Record*>(scq.StartEnqueue()); CHECK_NE(NULL, rec); - CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); - CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); - scq.FinishDequeue(); - CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); + *rec = i; + scq.FinishEnqueue(); } - // Now consumption must not be possible, as consumer now polls - // the first chunk for emptinness. - CHECK_EQ(NULL, scq.StartDequeue()); - - scq.FlushResidualRecords(); - // From now, consumer no more polls ahead of the current chunk, - // so it's possible to consume the second chunk. - CHECK_NE(NULL, scq.StartDequeue()); - // Consume the second chunk - for (Record i = 10; i < 10 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); + + // Consume all available kMaxRecordsInQueue / 2 records. + CHECK_NE(NULL, scq.Peek()); + for (Record i = 0; i < kMaxRecordsInQueue / 2; ++i) { + Record* rec = reinterpret_cast<Record*>(scq.Peek()); CHECK_NE(NULL, rec); CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); - CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); - scq.FinishDequeue(); - CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); + CHECK_EQ(rec, reinterpret_cast<Record*>(scq.Peek())); + scq.Remove(); + CHECK_NE(rec, reinterpret_cast<Record*>(scq.Peek())); } - // Consumption must still be possible as the first cell of the - // last chunk is not clean. - CHECK_NE(NULL, scq.StartDequeue()); + + // The queue is empty. + CHECK_EQ(NULL, scq.Peek()); } namespace { +typedef i::AtomicWord Record; +typedef SamplingCircularQueue<Record, 12> TestSampleQueue; + class ProducerThread: public i::Thread { public: - typedef SamplingCircularQueue::Cell Record; - - ProducerThread(SamplingCircularQueue* scq, + ProducerThread(TestSampleQueue* scq, int records_per_chunk, Record value, i::Semaphore* finished) @@ -117,16 +116,17 @@ class ProducerThread: public i::Thread { virtual void Run() { for (Record i = value_; i < value_ + records_per_chunk_; ++i) { - Record* rec = reinterpret_cast<Record*>(scq_->Enqueue()); + Record* rec = reinterpret_cast<Record*>(scq_->StartEnqueue()); CHECK_NE(NULL, rec); *rec = i; + scq_->FinishEnqueue(); } finished_->Signal(); } private: - SamplingCircularQueue* scq_; + TestSampleQueue* scq_; const int records_per_chunk_; Record value_; i::Semaphore* finished_; @@ -140,58 +140,49 @@ TEST(SamplingCircularQueueMultithreading) { // to the case of profiling under Linux, where signal handler that // does sampling is called in the context of different VM threads. - typedef ProducerThread::Record Record; const int kRecordsPerChunk = 4; - SamplingCircularQueue scq(sizeof(Record), - kRecordsPerChunk * sizeof(Record), - 3); - i::Semaphore* semaphore = i::OS::CreateSemaphore(0); - // Don't poll ahead, making possible to check data in the buffer - // immediately after enqueuing. - scq.FlushResidualRecords(); + TestSampleQueue scq; + i::Semaphore semaphore(0); - // Check that we are using non-reserved values. - ProducerThread producer1(&scq, kRecordsPerChunk, 1, semaphore); - ProducerThread producer2(&scq, kRecordsPerChunk, 10, semaphore); - ProducerThread producer3(&scq, kRecordsPerChunk, 20, semaphore); + ProducerThread producer1(&scq, kRecordsPerChunk, 1, &semaphore); + ProducerThread producer2(&scq, kRecordsPerChunk, 10, &semaphore); + ProducerThread producer3(&scq, kRecordsPerChunk, 20, &semaphore); - CHECK_EQ(NULL, scq.StartDequeue()); + CHECK_EQ(NULL, scq.Peek()); producer1.Start(); - semaphore->Wait(); + semaphore.Wait(); for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); + Record* rec = reinterpret_cast<Record*>(scq.Peek()); CHECK_NE(NULL, rec); CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); - CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); - scq.FinishDequeue(); - CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); + CHECK_EQ(rec, reinterpret_cast<Record*>(scq.Peek())); + scq.Remove(); + CHECK_NE(rec, reinterpret_cast<Record*>(scq.Peek())); } - CHECK_EQ(NULL, scq.StartDequeue()); + CHECK_EQ(NULL, scq.Peek()); producer2.Start(); - semaphore->Wait(); + semaphore.Wait(); for (Record i = 10; i < 10 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); + Record* rec = reinterpret_cast<Record*>(scq.Peek()); CHECK_NE(NULL, rec); CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); - CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); - scq.FinishDequeue(); - CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); + CHECK_EQ(rec, reinterpret_cast<Record*>(scq.Peek())); + scq.Remove(); + CHECK_NE(rec, reinterpret_cast<Record*>(scq.Peek())); } - CHECK_EQ(NULL, scq.StartDequeue()); + CHECK_EQ(NULL, scq.Peek()); producer3.Start(); - semaphore->Wait(); + semaphore.Wait(); for (Record i = 20; i < 20 + kRecordsPerChunk; ++i) { - Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); + Record* rec = reinterpret_cast<Record*>(scq.Peek()); CHECK_NE(NULL, rec); CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); - CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); - scq.FinishDequeue(); - CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); + CHECK_EQ(rec, reinterpret_cast<Record*>(scq.Peek())); + scq.Remove(); + CHECK_NE(rec, reinterpret_cast<Record*>(scq.Peek())); } - CHECK_EQ(NULL, scq.StartDequeue()); - - delete semaphore; + CHECK_EQ(NULL, scq.Peek()); } diff --git a/deps/v8/test/cctest/test-code-stubs-arm.cc b/deps/v8/test/cctest/test-code-stubs-arm.cc new file mode 100644 index 0000000000..c99433edad --- /dev/null +++ b/deps/v8/test/cctest/test-code-stubs-arm.cc @@ -0,0 +1,185 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Rrdistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Rrdistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Rrdistributions 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 "cctest.h" +#include "code-stubs.h" +#include "test-code-stubs.h" +#include "factory.h" +#include "macro-assembler.h" +#include "platform.h" +#include "simulator.h" + +using namespace v8::internal; + +#define __ masm. + +ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, + Register source_reg, + Register destination_reg, + bool inline_fastpath) { + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, + &actual_size, + true)); + CHECK(buffer); + HandleScope handles(isolate); + MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size)); + masm.set_allow_stub_calls(false); + DoubleToIStub stub(source_reg, destination_reg, 0, true, inline_fastpath); + + byte* start = stub.GetCode(isolate)->instruction_start(); + Label done; + + // Save callee save registers. + __ Push(r7, r6, r5, r4); + __ Push(lr); + + // For softfp, move the input value into d0. + if (!masm.use_eabi_hardfloat()) { + __ vmov(d0, r0, r1); + } + // Push the double argument. + __ sub(sp, sp, Operand(kDoubleSize)); + __ vstr(d0, sp, 0); + if (!source_reg.is(sp)) { + __ mov(source_reg, sp); + } + + // Save registers make sure they don't get clobbered. + int source_reg_offset = kDoubleSize; + int reg_num = 0; + for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) { + Register reg = Register::from_code(reg_num); + if (!reg.is(destination_reg)) { + __ push(reg); + source_reg_offset += kPointerSize; + } + } + + // Re-push the double argument. + __ sub(sp, sp, Operand(kDoubleSize)); + __ vstr(d0, sp, 0); + + // Call through to the actual stub + if (inline_fastpath) { + __ vldr(d0, MemOperand(source_reg)); + __ TryInlineTruncateDoubleToI(destination_reg, d0, &done); + if (destination_reg.is(source_reg) && !source_reg.is(sp)) { + // Restore clobbered source_reg. + __ add(source_reg, sp, Operand(source_reg_offset)); + } + } + __ Call(start, RelocInfo::EXTERNAL_REFERENCE); + __ bind(&done); + + __ add(sp, sp, Operand(kDoubleSize)); + + // Make sure no registers have been unexpectedly clobbered + for (--reg_num; reg_num >= 0; --reg_num) { + Register reg = Register::from_code(reg_num); + if (!reg.is(destination_reg)) { + __ ldr(ip, MemOperand(sp, 0)); + __ cmp(reg, ip); + __ Assert(eq, kRegisterWasClobbered); + __ add(sp, sp, Operand(kPointerSize)); + } + } + + __ add(sp, sp, Operand(kDoubleSize)); + + if (!destination_reg.is(r0)) + __ mov(r0, destination_reg); + + // Restore callee save registers. + __ Pop(lr); + __ Pop(r7, r6, r5, r4); + + __ Ret(0); + + CodeDesc desc; + masm.GetCode(&desc); + CPU::FlushICache(buffer, actual_size); + return (reinterpret_cast<ConvertDToIFunc>( + reinterpret_cast<intptr_t>(buffer))); +} + +#undef __ + + +static Isolate* GetIsolateFrom(LocalContext* context) { + return reinterpret_cast<Isolate*>((*context)->GetIsolate()); +} + + +int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, + double from) { +#ifdef USE_SIMULATOR + return reinterpret_cast<int32_t>(CALL_GENERATED_CODE(func, from, 0, 0, 0, 0)); +#else + return (*func)(from); +#endif +} + + +TEST(ConvertDToI) { + CcTest::InitializeVM(); + LocalContext context; + Isolate* isolate = GetIsolateFrom(&context); + HandleScope scope(isolate); + +#if DEBUG + // Verify that the tests actually work with the C version. In the release + // code, the compiler optimizes it away because it's all constant, but does it + // wrong, triggering an assert on gcc. + RunAllTruncationTests(&ConvertDToICVersion); +#endif + + Register source_registers[] = {sp, r0, r1, r2, r3, r4, r5, r6, r7}; + Register dest_registers[] = {r0, r1, r2, r3, r4, r5, r6, r7}; + + for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { + for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { + RunAllTruncationTests( + RunGeneratedCodeCallWrapper, + MakeConvertDToIFuncTrampoline(isolate, + source_registers[s], + dest_registers[d], + false)); + RunAllTruncationTests( + RunGeneratedCodeCallWrapper, + MakeConvertDToIFuncTrampoline(isolate, + source_registers[s], + dest_registers[d], + true)); + } + } +} diff --git a/deps/v8/test/cctest/test-code-stubs-ia32.cc b/deps/v8/test/cctest/test-code-stubs-ia32.cc index a3c0b54e25..3f621758e3 100644 --- a/deps/v8/test/cctest/test-code-stubs-ia32.cc +++ b/deps/v8/test/cctest/test-code-stubs-ia32.cc @@ -136,46 +136,15 @@ TEST(ConvertDToI) { RunAllTruncationTests(&ConvertDToICVersion); #endif - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esp, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, eax, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ebx, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, ecx, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edx, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, esi, esi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, eax)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, ebx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, ecx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, edx)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, edi)); - RunAllTruncationTests(MakeConvertDToIFuncTrampoline(isolate, edi, esi)); + Register source_registers[] = {esp, eax, ebx, ecx, edx, edi, esi}; + Register dest_registers[] = {eax, ebx, ecx, edx, edi, esi}; + + for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { + for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { + RunAllTruncationTests( + MakeConvertDToIFuncTrampoline(isolate, + source_registers[s], + dest_registers[d])); + } + } } diff --git a/deps/v8/test/cctest/test-code-stubs-x64.cc b/deps/v8/test/cctest/test-code-stubs-x64.cc index 0bffb87fef..4af5b45d7c 100644 --- a/deps/v8/test/cctest/test-code-stubs-x64.cc +++ b/deps/v8/test/cctest/test-code-stubs-x64.cc @@ -138,8 +138,8 @@ TEST(ConvertDToI) { Register source_registers[] = {rsp, rax, rbx, rcx, rdx, rsi, rdi, r8, r9}; Register dest_registers[] = {rax, rbx, rcx, rdx, rsi, rdi, r8, r9}; - for (size_t s = 0; s < sizeof(*source_registers); s++) { - for (size_t d = 0; d < sizeof(*dest_registers); d++) { + for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { + for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { RunAllTruncationTests( MakeConvertDToIFuncTrampoline(isolate, source_registers[s], diff --git a/deps/v8/test/cctest/test-code-stubs.cc b/deps/v8/test/cctest/test-code-stubs.cc index 405069626b..db00e9ac5a 100644 --- a/deps/v8/test/cctest/test-code-stubs.cc +++ b/deps/v8/test/cctest/test-code-stubs.cc @@ -42,8 +42,9 @@ using namespace v8::internal; int STDCALL ConvertDToICVersion(double d) { - Address double_ptr = reinterpret_cast<Address>(&d); - uint32_t exponent_bits = Memory::uint32_at(double_ptr + kDoubleSize / 2); + union { double d; uint32_t u[2]; } dbl; + dbl.d = d; + uint32_t exponent_bits = dbl.u[1]; int32_t shifted_mask = static_cast<int32_t>(Double::kExponentMask >> 32); int32_t exponent = (((exponent_bits & shifted_mask) >> (Double::kPhysicalSignificandSize - 32)) - @@ -54,8 +55,7 @@ int STDCALL ConvertDToICVersion(double d) { static_cast<uint32_t>(Double::kPhysicalSignificandSize); if (unsigned_exponent >= max_exponent) { if ((exponent - Double::kPhysicalSignificandSize) < 32) { - result = Memory::uint32_at(double_ptr) << - (exponent - Double::kPhysicalSignificandSize); + result = dbl.u[0] << (exponent - Double::kPhysicalSignificandSize); } } else { uint64_t big_result = @@ -71,22 +71,37 @@ int STDCALL ConvertDToICVersion(double d) { } -void RunOneTruncationTestWithTest(ConvertDToIFunc func, +void RunOneTruncationTestWithTest(ConvertDToICallWrapper callWrapper, + ConvertDToIFunc func, double from, double raw) { uint64_t to = static_cast<int64_t>(raw); - int result = (*func)(from); + int result = (*callWrapper)(func, from); CHECK_EQ(static_cast<int>(to), result); } +int32_t DefaultCallWrapper(ConvertDToIFunc func, + double from) { + return (*func)(from); +} + + // #define NaN and Infinity so that it's possible to cut-and-paste these tests // directly to a .js file and run them. #define NaN (OS::nan_value()) #define Infinity (std::numeric_limits<double>::infinity()) -#define RunOneTruncationTest(p1, p2) RunOneTruncationTestWithTest(func, p1, p2) +#define RunOneTruncationTest(p1, p2) \ + RunOneTruncationTestWithTest(callWrapper, func, p1, p2) + void RunAllTruncationTests(ConvertDToIFunc func) { + RunAllTruncationTests(DefaultCallWrapper, func); +} + + +void RunAllTruncationTests(ConvertDToICallWrapper callWrapper, + ConvertDToIFunc func) { RunOneTruncationTest(0, 0); RunOneTruncationTest(0.5, 0); RunOneTruncationTest(-0.5, 0); diff --git a/deps/v8/test/cctest/test-code-stubs.h b/deps/v8/test/cctest/test-code-stubs.h index eab8e63b2a..910e0d1701 100644 --- a/deps/v8/test/cctest/test-code-stubs.h +++ b/deps/v8/test/cctest/test-code-stubs.h @@ -41,8 +41,13 @@ typedef int32_t STDCALL ConvertDToIFuncType(double input); typedef ConvertDToIFuncType* ConvertDToIFunc; +typedef int32_t ConvertDToICallWrapperType(ConvertDToIFunc func, double from); +typedef ConvertDToICallWrapperType* ConvertDToICallWrapper; + int STDCALL ConvertDToICVersion(double d); void RunAllTruncationTests(ConvertDToIFunc func); +void RunAllTruncationTests(ConvertDToICallWrapper callWrapper, + ConvertDToIFunc func); #endif diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index b5ba46c4cb..7e87e10991 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -116,7 +116,7 @@ static Handle<JSFunction> Compile(const char* source) { } -static double Inc(int x) { +static double Inc(Isolate* isolate, int x) { const char* source = "result = %d + 1;"; EmbeddedVector<char, 512> buffer; OS::SNPrintF(buffer, source, x); @@ -125,8 +125,8 @@ static double Inc(int x) { if (fun.is_null()) return -1; bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(isolate->context()->global_object()); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); } @@ -135,19 +135,19 @@ static double Inc(int x) { TEST(Inc) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - CHECK_EQ(4.0, Inc(3)); + CHECK_EQ(4.0, Inc(CcTest::i_isolate(), 3)); } -static double Add(int x, int y) { +static double Add(Isolate* isolate, int x, int y) { Handle<JSFunction> fun = Compile("result = x + y;"); if (fun.is_null()) return -1; SetGlobalProperty("x", Smi::FromInt(x)); SetGlobalProperty("y", Smi::FromInt(y)); bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(isolate->context()->global_object()); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); } @@ -156,18 +156,18 @@ static double Add(int x, int y) { TEST(Add) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - CHECK_EQ(5.0, Add(2, 3)); + CHECK_EQ(5.0, Add(CcTest::i_isolate(), 2, 3)); } -static double Abs(int x) { +static double Abs(Isolate* isolate, int x) { Handle<JSFunction> fun = Compile("if (x < 0) result = -x; else result = x;"); if (fun.is_null()) return -1; SetGlobalProperty("x", Smi::FromInt(x)); bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(isolate->context()->global_object()); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); } @@ -176,19 +176,19 @@ static double Abs(int x) { TEST(Abs) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - CHECK_EQ(3.0, Abs(-3)); + CHECK_EQ(3.0, Abs(CcTest::i_isolate(), -3)); } -static double Sum(int n) { +static double Sum(Isolate* isolate, int n) { Handle<JSFunction> fun = Compile("s = 0; while (n > 0) { s += n; n -= 1; }; result = s;"); if (fun.is_null()) return -1; SetGlobalProperty("n", Smi::FromInt(n)); bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(isolate->context()->global_object()); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); return GetGlobalProperty("result")->ToObjectChecked()->Number(); } @@ -197,7 +197,7 @@ static double Sum(int n) { TEST(Sum) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - CHECK_EQ(5050.0, Sum(100)); + CHECK_EQ(5050.0, Sum(CcTest::i_isolate(), 100)); } @@ -208,8 +208,9 @@ TEST(Print) { Handle<JSFunction> fun = Compile(source); if (fun.is_null()) return; bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(CcTest::i_isolate()->context()->global_object()); + Execution::Call( + CcTest::i_isolate(), fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); } @@ -241,8 +242,9 @@ TEST(Stuff) { Handle<JSFunction> fun = Compile(source); CHECK(!fun.is_null()); bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(CcTest::i_isolate()->context()->global_object()); + Execution::Call( + CcTest::i_isolate(), fun, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); CHECK_EQ(511.0, GetGlobalProperty("r")->ToObjectChecked()->Number()); } @@ -258,7 +260,7 @@ TEST(UncaughtThrow) { bool has_pending_exception; Isolate* isolate = fun->GetIsolate(); Handle<JSObject> global(isolate->context()->global_object()); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); CHECK(has_pending_exception); CHECK_EQ(42.0, isolate->pending_exception()->ToObjectChecked()->Number()); } @@ -282,8 +284,9 @@ TEST(C2JSFrames) { // Run the generated code to populate the global object with 'foo'. bool has_pending_exception; - Handle<JSObject> global(Isolate::Current()->context()->global_object()); - Execution::Call(fun0, global, 0, NULL, &has_pending_exception); + Handle<JSObject> global(isolate->context()->global_object()); + Execution::Call( + isolate, fun0, global, 0, NULL, &has_pending_exception); CHECK(!has_pending_exception); Object* foo_string = isolate->factory()->InternalizeOneByteString( @@ -295,7 +298,8 @@ TEST(C2JSFrames) { Handle<Object> argv[] = { isolate->factory()->InternalizeOneByteString( STATIC_ASCII_VECTOR("hello")) }; - Execution::Call(Handle<JSFunction>::cast(fun1), + Execution::Call(isolate, + Handle<JSFunction>::cast(fun1), global, ARRAY_SIZE(argv), argv, diff --git a/deps/v8/test/cctest/test-condition-variable.cc b/deps/v8/test/cctest/test-condition-variable.cc new file mode 100644 index 0000000000..a7bd6500dc --- /dev/null +++ b/deps/v8/test/cctest/test-condition-variable.cc @@ -0,0 +1,304 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "v8.h" + +#include "cctest.h" +#include "platform/condition-variable.h" +#include "platform/time.h" + +using namespace ::v8::internal; + + +TEST(WaitForAfterNofityOnSameThread) { + for (int n = 0; n < 10; ++n) { + Mutex mutex; + ConditionVariable cv; + + LockGuard<Mutex> lock_guard(&mutex); + + cv.NotifyOne(); + CHECK_EQ(false, cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n))); + + cv.NotifyAll(); + CHECK_EQ(false, cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n))); + } +} + + +class ThreadWithMutexAndConditionVariable V8_FINAL : public Thread { + public: + ThreadWithMutexAndConditionVariable() + : Thread("ThreadWithMutexAndConditionVariable"), + running_(false), finished_(false) {} + virtual ~ThreadWithMutexAndConditionVariable() {} + + virtual void Run() V8_OVERRIDE { + LockGuard<Mutex> lock_guard(&mutex_); + running_ = true; + cv_.NotifyOne(); + while (running_) { + cv_.Wait(&mutex_); + } + finished_ = true; + cv_.NotifyAll(); + } + + bool running_; + bool finished_; + ConditionVariable cv_; + Mutex mutex_; +}; + + +TEST(MultipleThreadsWithSeparateConditionVariables) { + static const int kThreadCount = 128; + ThreadWithMutexAndConditionVariable threads[kThreadCount]; + + for (int n = 0; n < kThreadCount; ++n) { + LockGuard<Mutex> lock_guard(&threads[n].mutex_); + CHECK(!threads[n].running_); + CHECK(!threads[n].finished_); + threads[n].Start(); + // Wait for nth thread to start. + while (!threads[n].running_) { + threads[n].cv_.Wait(&threads[n].mutex_); + } + } + + for (int n = kThreadCount - 1; n >= 0; --n) { + LockGuard<Mutex> lock_guard(&threads[n].mutex_); + CHECK(threads[n].running_); + CHECK(!threads[n].finished_); + } + + for (int n = 0; n < kThreadCount; ++n) { + LockGuard<Mutex> lock_guard(&threads[n].mutex_); + CHECK(threads[n].running_); + CHECK(!threads[n].finished_); + // Tell the nth thread to quit. + threads[n].running_ = false; + threads[n].cv_.NotifyOne(); + } + + for (int n = kThreadCount - 1; n >= 0; --n) { + // Wait for nth thread to quit. + LockGuard<Mutex> lock_guard(&threads[n].mutex_); + while (!threads[n].finished_) { + threads[n].cv_.Wait(&threads[n].mutex_); + } + CHECK(!threads[n].running_); + CHECK(threads[n].finished_); + } + + for (int n = 0; n < kThreadCount; ++n) { + threads[n].Join(); + LockGuard<Mutex> lock_guard(&threads[n].mutex_); + CHECK(!threads[n].running_); + CHECK(threads[n].finished_); + } +} + + +class ThreadWithSharedMutexAndConditionVariable V8_FINAL : public Thread { + public: + ThreadWithSharedMutexAndConditionVariable() + : Thread("ThreadWithSharedMutexAndConditionVariable"), + running_(false), finished_(false), cv_(NULL), mutex_(NULL) {} + virtual ~ThreadWithSharedMutexAndConditionVariable() {} + + virtual void Run() V8_OVERRIDE { + LockGuard<Mutex> lock_guard(mutex_); + running_ = true; + cv_->NotifyAll(); + while (running_) { + cv_->Wait(mutex_); + } + finished_ = true; + cv_->NotifyAll(); + } + + bool running_; + bool finished_; + ConditionVariable* cv_; + Mutex* mutex_; +}; + + +TEST(MultipleThreadsWithSharedSeparateConditionVariables) { + static const int kThreadCount = 128; + ThreadWithSharedMutexAndConditionVariable threads[kThreadCount]; + ConditionVariable cv; + Mutex mutex; + + for (int n = 0; n < kThreadCount; ++n) { + threads[n].mutex_ = &mutex; + threads[n].cv_ = &cv; + } + + // Start all threads. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = 0; n < kThreadCount; ++n) { + CHECK(!threads[n].running_); + CHECK(!threads[n].finished_); + threads[n].Start(); + } + } + + // Wait for all threads to start. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = kThreadCount - 1; n >= 0; --n) { + while (!threads[n].running_) { + cv.Wait(&mutex); + } + } + } + + // Make sure that all threads are running. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = 0; n < kThreadCount; ++n) { + CHECK(threads[n].running_); + CHECK(!threads[n].finished_); + } + } + + // Tell all threads to quit. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = kThreadCount - 1; n >= 0; --n) { + CHECK(threads[n].running_); + CHECK(!threads[n].finished_); + // Tell the nth thread to quit. + threads[n].running_ = false; + } + cv.NotifyAll(); + } + + // Wait for all threads to quit. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = 0; n < kThreadCount; ++n) { + while (!threads[n].finished_) { + cv.Wait(&mutex); + } + } + } + + // Make sure all threads are finished. + { + LockGuard<Mutex> lock_guard(&mutex); + for (int n = kThreadCount - 1; n >= 0; --n) { + CHECK(!threads[n].running_); + CHECK(threads[n].finished_); + } + } + + // Join all threads. + for (int n = 0; n < kThreadCount; ++n) { + threads[n].Join(); + } +} + + +class LoopIncrementThread V8_FINAL : public Thread { + public: + LoopIncrementThread(int rem, + int* counter, + int limit, + int thread_count, + ConditionVariable* cv, + Mutex* mutex) + : Thread("LoopIncrementThread"), rem_(rem), counter_(counter), + limit_(limit), thread_count_(thread_count), cv_(cv), mutex_(mutex) { + CHECK_LT(rem, thread_count); + CHECK_EQ(0, limit % thread_count); + } + + virtual void Run() V8_OVERRIDE { + int last_count = -1; + while (true) { + LockGuard<Mutex> lock_guard(mutex_); + int count = *counter_; + while (count % thread_count_ != rem_ && count < limit_) { + cv_->Wait(mutex_); + count = *counter_; + } + if (count >= limit_) break; + CHECK_EQ(*counter_, count); + if (last_count != -1) { + CHECK_EQ(last_count + (thread_count_ - 1), count); + } + count++; + *counter_ = count; + last_count = count; + cv_->NotifyAll(); + } + } + + private: + const int rem_; + int* counter_; + const int limit_; + const int thread_count_; + ConditionVariable* cv_; + Mutex* mutex_; +}; + + +TEST(LoopIncrement) { + static const int kMaxThreadCount = 16; + Mutex mutex; + ConditionVariable cv; + for (int thread_count = 1; thread_count < kMaxThreadCount; ++thread_count) { + int limit = thread_count * 100; + int counter = 0; + + // Setup the threads. + Thread** threads = new Thread*[thread_count]; + for (int n = 0; n < thread_count; ++n) { + threads[n] = new LoopIncrementThread( + n, &counter, limit, thread_count, &cv, &mutex); + } + + // Start all threads. + for (int n = thread_count - 1; n >= 0; --n) { + threads[n]->Start(); + } + + // Join and cleanup all threads. + for (int n = 0; n < thread_count; ++n) { + threads[n]->Join(); + delete threads[n]; + } + delete[] threads; + + CHECK_EQ(limit, counter); + } +} diff --git a/deps/v8/test/cctest/test-cpu-ia32.cc b/deps/v8/test/cctest/test-cpu-ia32.cc new file mode 100644 index 0000000000..245450bf92 --- /dev/null +++ b/deps/v8/test/cctest/test-cpu-ia32.cc @@ -0,0 +1,40 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "v8.h" + +#include "cctest.h" +#include "cpu.h" + +using namespace v8::internal; + + +TEST(RequiredFeaturesX64) { + // Test for the features required by every x86 CPU in compat/legacy mode. + CPU cpu; + CHECK(cpu.has_sahf()); +} diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc index 7b5fc2b0fe..4708f506d2 100644 --- a/deps/v8/test/cctest/test-cpu-profiler.cc +++ b/deps/v8/test/cctest/test-cpu-profiler.cc @@ -31,6 +31,7 @@ #include "cpu-profiler-inl.h" #include "cctest.h" #include "platform.h" +#include "smart-pointers.h" #include "utils.h" #include "../include/v8-profiler.h" using i::CodeEntry; @@ -42,16 +43,19 @@ using i::ProfileGenerator; using i::ProfileNode; using i::ProfilerEventsProcessor; using i::ScopedVector; +using i::SmartPointer; +using i::TimeDelta; using i::Vector; TEST(StartStop) { - CpuProfilesCollection profiles; + i::Isolate* isolate = CcTest::i_isolate(); + CpuProfilesCollection profiles(isolate->heap()); ProfileGenerator generator(&profiles); - ProfilerEventsProcessor processor(&generator); - processor.Start(); - processor.StopSynchronously(); - processor.Join(); + SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( + &generator, NULL, TimeDelta::FromMicroseconds(100))); + processor->Start(); + processor->StopSynchronously(); } @@ -63,7 +67,7 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, i::Address frame1, i::Address frame2 = NULL, i::Address frame3 = NULL) { - i::TickSample* sample = proc->TickSampleEvent(); + i::TickSample* sample = proc->StartTickSample(); sample->pc = frame1; sample->tos = frame1; sample->frames_count = 0; @@ -75,6 +79,7 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, sample->stack[1] = frame3; sample->frames_count = 2; } + proc->FinishTickSample(); } namespace { @@ -136,12 +141,13 @@ TEST(CodeEvents) { i::Code* args3_code = CreateCode(&env); i::Code* args4_code = CreateCode(&env); - CpuProfilesCollection* profiles = new CpuProfilesCollection; + CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap()); profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - ProfilerEventsProcessor processor(&generator); - processor.Start(); - CpuProfiler profiler(isolate, profiles, &generator, &processor); + SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( + &generator, NULL, TimeDelta::FromMicroseconds(100))); + processor->Start(); + CpuProfiler profiler(isolate, profiles, &generator, *processor); // Enqueue code creation events. const char* aaa_str = "aaa"; @@ -156,10 +162,9 @@ TEST(CodeEvents) { profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4); // Enqueue a tick event to enable code events processing. - EnqueueTickSampleEvent(&processor, aaa_code->address()); + EnqueueTickSampleEvent(*processor, aaa_code->address()); - processor.StopSynchronously(); - processor.Join(); + processor->StopSynchronously(); // Check the state of profile generator. CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address()); @@ -198,30 +203,30 @@ TEST(TickEvents) { i::Code* frame2_code = CreateCode(&env); i::Code* frame3_code = CreateCode(&env); - CpuProfilesCollection* profiles = new CpuProfilesCollection; + CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap()); profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - ProfilerEventsProcessor processor(&generator); - processor.Start(); - CpuProfiler profiler(isolate, profiles, &generator, &processor); + SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( + &generator, NULL, TimeDelta::FromMicroseconds(100))); + processor->Start(); + CpuProfiler profiler(isolate, profiles, &generator, *processor); profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb"); profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5); profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd"); - EnqueueTickSampleEvent(&processor, frame1_code->instruction_start()); + EnqueueTickSampleEvent(*processor, frame1_code->instruction_start()); EnqueueTickSampleEvent( - &processor, + *processor, frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2, frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2); EnqueueTickSampleEvent( - &processor, + *processor, frame3_code->instruction_end() - 1, frame2_code->instruction_end() - 1, frame1_code->instruction_end() - 1); - processor.StopSynchronously(); - processor.Join(); + processor->StopSynchronously(); CpuProfile* profile = profiles->StopProfiling(""); CHECK_NE(NULL, profile); @@ -267,25 +272,26 @@ TEST(Issue1398) { i::Code* code = CreateCode(&env); - CpuProfilesCollection* profiles = new CpuProfilesCollection; + CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap()); profiles->StartProfiling("", 1, false); ProfileGenerator generator(profiles); - ProfilerEventsProcessor processor(&generator); - processor.Start(); - CpuProfiler profiler(isolate, profiles, &generator, &processor); + SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( + &generator, NULL, TimeDelta::FromMicroseconds(100))); + processor->Start(); + CpuProfiler profiler(isolate, profiles, &generator, *processor); profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); - i::TickSample* sample = processor.TickSampleEvent(); + i::TickSample* sample = processor->StartTickSample(); sample->pc = code->address(); sample->tos = 0; sample->frames_count = i::TickSample::kMaxFramesCount; for (int i = 0; i < sample->frames_count; ++i) { sample->stack[i] = code->address(); } + processor->FinishTickSample(); - processor.StopSynchronously(); - processor.Join(); + processor->StopSynchronously(); CpuProfile* profile = profiles->StopProfiling(""); CHECK_NE(NULL, profile); @@ -415,13 +421,10 @@ TEST(ProfileStartEndTime) { v8::HandleScope scope(env->GetIsolate()); v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); - int64_t time_before_profiling = i::OS::Ticks(); v8::Local<v8::String> profile_name = v8::String::New("test"); cpu_profiler->StartCpuProfiling(profile_name); const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); - CHECK(time_before_profiling <= profile->GetStartTime()); CHECK(profile->GetStartTime() <= profile->GetEndTime()); - CHECK(profile->GetEndTime() <= i::OS::Ticks()); } @@ -1368,13 +1371,11 @@ TEST(IdleTime) { const v8::CpuProfileNode* programNode = GetChild(root, ProfileGenerator::kProgramEntryName); CHECK_EQ(0, programNode->GetChildrenCount()); - CHECK_GE(programNode->GetSelfSamplesCount(), 3); CHECK_GE(programNode->GetHitCount(), 3); const v8::CpuProfileNode* idleNode = GetChild(root, ProfileGenerator::kIdleEntryName); CHECK_EQ(0, idleNode->GetChildrenCount()); - CHECK_GE(idleNode->GetSelfSamplesCount(), 3); CHECK_GE(idleNode->GetHitCount(), 3); cpu_profiler->DeleteAllCpuProfiles(); diff --git a/deps/v8/test/cctest/test-cpu-x64.cc b/deps/v8/test/cctest/test-cpu-x64.cc new file mode 100644 index 0000000000..a2c45cf862 --- /dev/null +++ b/deps/v8/test/cctest/test-cpu-x64.cc @@ -0,0 +1,44 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "v8.h" + +#include "cctest.h" +#include "cpu.h" + +using namespace v8::internal; + + +TEST(RequiredFeaturesX64) { + // Test for the features required by every x64 CPU. + CPU cpu; + CHECK(cpu.has_fpu()); + CHECK(cpu.has_cmov()); + CHECK(cpu.has_mmx()); + CHECK(cpu.has_sse()); + CHECK(cpu.has_sse2()); +} diff --git a/deps/v8/test/cctest/test-lock.cc b/deps/v8/test/cctest/test-cpu.cc index d4387d0f90..06966c68c8 100644 --- a/deps/v8/test/cctest/test-lock.cc +++ b/deps/v8/test/cctest/test-cpu.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2013 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -24,66 +24,32 @@ // 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. -// -// Tests of the TokenLock class from lock.h - -#include <stdlib.h> #include "v8.h" -#include "platform.h" #include "cctest.h" +#include "cpu.h" +using namespace v8::internal; -using namespace ::v8::internal; +TEST(FeatureImplications) { + // Test for features implied by other features. + CPU cpu; -// Simple test of locking logic -TEST(Simple) { - Mutex* mutex = OS::CreateMutex(); - CHECK_EQ(0, mutex->Lock()); // acquire the lock with the right token - CHECK_EQ(0, mutex->Unlock()); // can unlock with the right token - delete mutex; -} + // ia32 and x64 features + CHECK(!cpu.has_sse() || cpu.has_mmx()); + CHECK(!cpu.has_sse2() || cpu.has_sse()); + CHECK(!cpu.has_sse3() || cpu.has_sse2()); + CHECK(!cpu.has_ssse3() || cpu.has_sse3()); + CHECK(!cpu.has_sse41() || cpu.has_sse3()); + CHECK(!cpu.has_sse42() || cpu.has_sse41()); - -TEST(MultiLock) { - Mutex* mutex = OS::CreateMutex(); - CHECK_EQ(0, mutex->Lock()); - CHECK_EQ(0, mutex->Unlock()); - delete mutex; + // arm features + CHECK(!cpu.has_vfp3_d32() || cpu.has_vfp3()); } -TEST(ShallowLock) { - Mutex* mutex = OS::CreateMutex(); - CHECK_EQ(0, mutex->Lock()); - CHECK_EQ(0, mutex->Unlock()); - CHECK_EQ(0, mutex->Lock()); - CHECK_EQ(0, mutex->Unlock()); - delete mutex; -} - - -TEST(SemaphoreTimeout) { - bool ok; - Semaphore* sem = OS::CreateSemaphore(0); - - // Semaphore not signalled - timeout. - ok = sem->Wait(0); - CHECK(!ok); - ok = sem->Wait(100); - CHECK(!ok); - ok = sem->Wait(1000); - CHECK(!ok); - - // Semaphore signalled - no timeout. - sem->Signal(); - ok = sem->Wait(0); - sem->Signal(); - ok = sem->Wait(100); - sem->Signal(); - ok = sem->Wait(1000); - CHECK(ok); - delete sem; +TEST(NumberOfProcessorsOnline) { + CHECK_GT(CPU::NumberOfProcessorsOnline(), 0); } diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 484eb8e3fb..2540a3dfe5 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -37,12 +37,19 @@ #include "compilation-cache.h" #include "debug.h" #include "deoptimizer.h" +#include "frames.h" #include "platform.h" +#include "platform/condition-variable.h" +#include "platform/socket.h" #include "stub-cache.h" #include "utils.h" #undef V8_DISABLE_DEPRECATIONS +using ::v8::internal::Mutex; +using ::v8::internal::LockGuard; +using ::v8::internal::ConditionVariable; +using ::v8::internal::Semaphore; using ::v8::internal::EmbeddedVector; using ::v8::internal::Object; using ::v8::internal::OS; @@ -54,6 +61,7 @@ using ::v8::internal::Debug; using ::v8::internal::Debugger; using ::v8::internal::CommandMessage; using ::v8::internal::CommandMessageQueue; +using ::v8::internal::StackFrame; using ::v8::internal::StepAction; using ::v8::internal::StepIn; // From StepAction enum using ::v8::internal::StepNext; // From StepAction enum @@ -384,7 +392,7 @@ static void ChangeBreakOnExceptionFromJS(bool caught, bool uncaught) { // Prepare to step to next break location. static void PrepareStep(StepAction step_action) { v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); - debug->PrepareStep(step_action, 1); + debug->PrepareStep(step_action, 1, StackFrame::NO_ID); } @@ -661,10 +669,11 @@ int last_source_column = -1; // Debug event handler which counts the break points which have been hit. int break_point_hit_count = 0; int break_point_hit_count_deoptimize = 0; -static void DebugEventBreakPointHitCount(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventBreakPointHitCount( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); + v8::Handle<v8::Object> event_data = event_details.GetEventData(); v8::internal::Isolate* isolate = v8::internal::Isolate::Current(); Debug* debug = isolate->debug(); // When hitting a debug event listener there must be a break set. @@ -773,10 +782,11 @@ static void DebugEventCounterClear() { uncaught_exception_hit_count = 0; } -static void DebugEventCounter(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventCounter( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); + v8::Handle<v8::Object> event_data = event_details.GetEventData(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. @@ -835,10 +845,10 @@ const char* evaluate_check_source = v8::Local<v8::Function> evaluate_check_function; // The actual debug event described by the longer comment above. -static void DebugEventEvaluate(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventEvaluate( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -862,10 +872,10 @@ static void DebugEventEvaluate(v8::DebugEvent event, // This debug event listener removes a breakpoint in a function int debug_event_remove_break_point = 0; -static void DebugEventRemoveBreakPoint(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventRemoveBreakPoint( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Value> data = event_details.GetCallbackData(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -881,10 +891,9 @@ static void DebugEventRemoveBreakPoint(v8::DebugEvent event, // Debug event handler which counts break points hit and performs a step // afterwards. StepAction step_action = StepIn; // Step action to perform when stepping. -static void DebugEventStep(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventStep( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -908,10 +917,10 @@ static void DebugEventStep(v8::DebugEvent event, const char* expected_step_sequence = NULL; // The actual debug event described by the longer comment above. -static void DebugEventStepSequence(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventStepSequence( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -939,10 +948,8 @@ static void DebugEventStepSequence(v8::DebugEvent event, // Debug event handler which performs a garbage collection. static void DebugEventBreakPointCollectGarbage( - v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -965,10 +972,9 @@ static void DebugEventBreakPointCollectGarbage( // Debug event handler which re-issues a debug break and calls the garbage // collector to have the heap verified. -static void DebugEventBreak(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventBreak( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug(); // When hitting a debug event listener there must be a break set. CHECK_NE(debug->break_id(), 0); @@ -991,10 +997,10 @@ static void DebugEventBreak(v8::DebugEvent event, // reached. int max_break_point_hit_count = 0; bool terminate_after_max_break_point_hit = false; -static void DebugEventBreakMax(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventBreakMax( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); v8::internal::Isolate* isolate = v8::internal::Isolate::Current(); v8::internal::Debug* debug = isolate->debug(); // When hitting a debug event listener there must be a break set. @@ -1179,8 +1185,7 @@ TEST(BreakPointICStore) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run(); v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); @@ -1201,7 +1206,7 @@ TEST(BreakPointICStore) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1211,8 +1216,7 @@ TEST(BreakPointICLoad) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("bar=1"))->Run(); v8::Script::Compile(v8::String::New("function foo(){var x=bar;}"))->Run(); v8::Local<v8::Function> foo = @@ -1234,7 +1238,7 @@ TEST(BreakPointICLoad) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1244,8 +1248,7 @@ TEST(BreakPointICCall) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function bar(){}"))->Run(); v8::Script::Compile(v8::String::New("function foo(){bar();}"))->Run(); v8::Local<v8::Function> foo = @@ -1267,7 +1270,7 @@ TEST(BreakPointICCall) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1277,8 +1280,7 @@ TEST(BreakPointICCallWithGC) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage); v8::Script::Compile(v8::String::New("function bar(){return 1;}"))->Run(); v8::Script::Compile(v8::String::New("function foo(){return bar();}"))->Run(); v8::Local<v8::Function> foo = @@ -1300,7 +1302,7 @@ TEST(BreakPointICCallWithGC) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1310,8 +1312,7 @@ TEST(BreakPointConstructCallWithGC) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage); v8::Script::Compile(v8::String::New("function bar(){ this.x = 1;}"))->Run(); v8::Script::Compile(v8::String::New( "function foo(){return new bar(1).x;}"))->Run(); @@ -1334,7 +1335,7 @@ TEST(BreakPointConstructCallWithGC) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1355,8 +1356,7 @@ TEST(BreakPointReturn) { "frame_source_column"); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function foo(){}"))->Run(); v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); @@ -1381,7 +1381,7 @@ TEST(BreakPointReturn) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1404,8 +1404,7 @@ TEST(GCDuringBreakPointProcessing) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage); v8::Local<v8::Function> foo; // Test IC store break point with garbage collection. @@ -1433,7 +1432,7 @@ TEST(GCDuringBreakPointProcessing) { SetBreakPoint(foo, 0); CallWithBreakPoints(env->Global(), foo, 1, 25); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1468,8 +1467,7 @@ TEST(BreakPointSurviveGC) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::Function> foo; // Test IC store break point with garbage collection. @@ -1515,7 +1513,7 @@ TEST(BreakPointSurviveGC) { CallAndGC(env->Global(), foo); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1527,8 +1525,7 @@ TEST(BreakPointThroughJavaScript) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function bar(){}"))->Run(); v8::Script::Compile(v8::String::New("function foo(){bar();bar();}"))->Run(); // 012345678901234567890 @@ -1566,7 +1563,7 @@ TEST(BreakPointThroughJavaScript) { foo->Run(); CHECK_EQ(8, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Make sure that the break point numbers are consecutive. @@ -1583,8 +1580,7 @@ TEST(ScriptBreakPointByNameThroughJavaScript) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script = v8::String::New( "function f() {\n" @@ -1668,7 +1664,7 @@ TEST(ScriptBreakPointByNameThroughJavaScript) { g->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Make sure that the break point numbers are consecutive. @@ -1687,8 +1683,7 @@ TEST(ScriptBreakPointByIdThroughJavaScript) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> source = v8::String::New( "function f() {\n" @@ -1776,7 +1771,7 @@ TEST(ScriptBreakPointByIdThroughJavaScript) { g->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Make sure that the break point numbers are consecutive. @@ -1796,8 +1791,7 @@ TEST(EnableDisableScriptBreakPoint) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script = v8::String::New( "function f() {\n" @@ -1841,7 +1835,7 @@ TEST(EnableDisableScriptBreakPoint) { f->Call(env->Global(), 0, NULL); CHECK_EQ(3, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1853,8 +1847,7 @@ TEST(ConditionalScriptBreakPoint) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script = v8::String::New( "count = 0;\n" @@ -1903,7 +1896,7 @@ TEST(ConditionalScriptBreakPoint) { } CHECK_EQ(5, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1915,8 +1908,7 @@ TEST(ScriptBreakPointIgnoreCount) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script = v8::String::New( "function f() {\n" @@ -1958,7 +1950,7 @@ TEST(ScriptBreakPointIgnoreCount) { } CHECK_EQ(5, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -1970,8 +1962,7 @@ TEST(ScriptBreakPointReload) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::Function> f; v8::Local<v8::String> script = v8::String::New( @@ -2017,7 +2008,7 @@ TEST(ScriptBreakPointReload) { f->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2029,8 +2020,7 @@ TEST(ScriptBreakPointMultiple) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::Function> f; v8::Local<v8::String> script_f = v8::String::New( @@ -2083,7 +2073,7 @@ TEST(ScriptBreakPointMultiple) { g->Call(env->Global(), 0, NULL); CHECK_EQ(2, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2095,8 +2085,7 @@ TEST(ScriptBreakPointLineOffset) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::Function> f; v8::Local<v8::String> script = v8::String::New( @@ -2139,7 +2128,7 @@ TEST(ScriptBreakPointLineOffset) { f->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2155,8 +2144,7 @@ TEST(ScriptBreakPointLine) { frame_function_name_source, "frame_function_name"); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::Function> f; v8::Local<v8::Function> g; @@ -2245,7 +2233,7 @@ TEST(ScriptBreakPointLine) { v8::Script::Compile(script, &origin)->Run(); CHECK_EQ(0, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2256,8 +2244,7 @@ TEST(ScriptBreakPointLineTopLevel) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script = v8::String::New( "function f() {\n" @@ -2290,7 +2277,7 @@ TEST(ScriptBreakPointLineTopLevel) { f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); CHECK_EQ(0, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2302,8 +2289,7 @@ TEST(ScriptBreakPointTopLevelCrash) { v8::HandleScope scope(env->GetIsolate()); env.ExposeDebug(); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Local<v8::String> script_source = v8::String::New( "function f() {\n" @@ -2323,7 +2309,7 @@ TEST(ScriptBreakPointTopLevelCrash) { ClearBreakPointFromJS(sbp1); ClearBreakPointFromJS(sbp2); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2339,7 +2325,7 @@ TEST(RemoveBreakPointInBreak) { debug_event_remove_break_point = SetBreakPoint(foo, 0); // Register the debug event listener pasing the function - v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo); + v8::Debug::SetDebugEventListener2(DebugEventRemoveBreakPoint, foo); break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); @@ -2349,7 +2335,7 @@ TEST(RemoveBreakPointInBreak) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2359,8 +2345,7 @@ TEST(DebuggerStatement) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function bar(){debugger}"))->Run(); v8::Script::Compile(v8::String::New( "function foo(){debugger;debugger;}"))->Run(); @@ -2377,7 +2362,7 @@ TEST(DebuggerStatement) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(3, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2387,8 +2372,7 @@ TEST(DebuggerStatementBreakpoint) { break_point_hit_count = 0; DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); v8::Script::Compile(v8::String::New("function foo(){debugger;}"))->Run(); v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); @@ -2404,7 +2388,7 @@ TEST(DebuggerStatementBreakpoint) { CHECK_EQ(2, break_point_hit_count); ClearBreakPoint(bp); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2421,7 +2405,7 @@ TEST(DebugEvaluate) { evaluate_check_source, "evaluate_check"); // Register the debug event listener - v8::Debug::SetDebugEventListener(DebugEventEvaluate); + v8::Debug::SetDebugEventListener2(DebugEventEvaluate); // Different expected vaules of x and a when in a break point (u = undefined, // d = Hello, world!). @@ -2521,7 +2505,7 @@ TEST(DebugEvaluate) { }; bar->Call(env->Global(), 2, argv_bar_3); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2702,17 +2686,12 @@ struct DebugProcessDebugMessagesData { DebugProcessDebugMessagesData process_debug_messages_data; static void DebugProcessDebugMessagesHandler( - const uint16_t* message, - int length, - v8::Debug::ClientData* client_data) { - - const int kBufferSize = 100000; - char print_buffer[kBufferSize]; - Utf16ToAscii(message, length, print_buffer, kBufferSize); - + const v8::Debug::Message& message) { + v8::Handle<v8::String> json = message.GetJSON(); + v8::String::AsciiValue ascii(json); EvaluateResult* array_item = process_debug_messages_data.current(); - bool res = GetEvaluateStringResult(print_buffer, + bool res = GetEvaluateStringResult(*ascii, array_item->buffer, EvaluateResult::kBufferSize); if (res) { @@ -2724,7 +2703,7 @@ static void DebugProcessDebugMessagesHandler( // Test that the evaluation of expressions works even from ProcessDebugMessages // i.e. with empty stack. TEST(DebugEvaluateWithoutStack) { - v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler); + v8::Debug::SetMessageHandler2(DebugProcessDebugMessagesHandler); DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -2778,8 +2757,8 @@ TEST(DebugEvaluateWithoutStack) { 0); CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0); - v8::Debug::SetMessageHandler(NULL); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetMessageHandler2(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2800,7 +2779,7 @@ TEST(DebugStepLinear) { SetBreakPoint(foo, 3); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); step_action = StepIn; break_point_hit_count = 0; @@ -2809,11 +2788,11 @@ TEST(DebugStepLinear) { // With stepping all break locations are hit. CHECK_EQ(4, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Register a debug event listener which just counts. - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); SetBreakPoint(foo, 3); break_point_hit_count = 0; @@ -2822,7 +2801,7 @@ TEST(DebugStepLinear) { // Without stepping only active break points are hit. CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2833,7 +2812,7 @@ TEST(DebugStepKeyedLoadLoop) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping of keyed load. The statement 'y=1' // is there to have more than one breakable statement in the loop, TODO(315). @@ -2870,7 +2849,7 @@ TEST(DebugStepKeyedLoadLoop) { // With stepping all break locations are hit. CHECK_EQ(34, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2881,7 +2860,7 @@ TEST(DebugStepKeyedStoreLoop) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping of keyed store. The statement 'y=1' // is there to have more than one breakable statement in the loop, TODO(315). @@ -2917,7 +2896,7 @@ TEST(DebugStepKeyedStoreLoop) { // With stepping all break locations are hit. CHECK_EQ(33, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2928,7 +2907,7 @@ TEST(DebugStepNamedLoadLoop) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping of named load. v8::Local<v8::Function> foo = CompileFunction( @@ -2961,7 +2940,7 @@ TEST(DebugStepNamedLoadLoop) { // With stepping all break locations are hit. CHECK_EQ(54, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -2971,7 +2950,7 @@ static void DoDebugStepNamedStoreLoop(int expected) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping of named store. v8::Local<v8::Function> foo = CompileFunction( @@ -2996,7 +2975,7 @@ static void DoDebugStepNamedStoreLoop(int expected) { // With stepping all expected break locations are hit. CHECK_EQ(expected, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3013,7 +2992,7 @@ TEST(DebugStepLinearMixedICs) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. v8::Local<v8::Function> foo = CompileFunction(&env, @@ -3036,11 +3015,11 @@ TEST(DebugStepLinearMixedICs) { // With stepping all break locations are hit. CHECK_EQ(11, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Register a debug event listener which just counts. - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); SetBreakPoint(foo, 0); break_point_hit_count = 0; @@ -3049,7 +3028,7 @@ TEST(DebugStepLinearMixedICs) { // Without stepping only active break points are hit. CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3059,7 +3038,7 @@ TEST(DebugStepDeclarations) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3082,7 +3061,7 @@ TEST(DebugStepDeclarations) { CHECK_EQ(6, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3092,7 +3071,7 @@ TEST(DebugStepLocals) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3115,7 +3094,7 @@ TEST(DebugStepLocals) { CHECK_EQ(6, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3125,7 +3104,7 @@ TEST(DebugStepIf) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3158,7 +3137,7 @@ TEST(DebugStepIf) { CHECK_EQ(5, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3168,7 +3147,7 @@ TEST(DebugStepSwitch) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3214,7 +3193,7 @@ TEST(DebugStepSwitch) { CHECK_EQ(7, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3224,7 +3203,7 @@ TEST(DebugStepWhile) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3254,7 +3233,7 @@ TEST(DebugStepWhile) { CHECK_EQ(202, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3264,7 +3243,7 @@ TEST(DebugStepDoWhile) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3294,7 +3273,7 @@ TEST(DebugStepDoWhile) { CHECK_EQ(202, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3304,7 +3283,7 @@ TEST(DebugStepFor) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3335,7 +3314,7 @@ TEST(DebugStepFor) { CHECK_EQ(203, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3345,7 +3324,7 @@ TEST(DebugStepForContinue) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3386,7 +3365,7 @@ TEST(DebugStepForContinue) { CHECK_EQ(456, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3396,7 +3375,7 @@ TEST(DebugStepForBreak) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3438,7 +3417,7 @@ TEST(DebugStepForBreak) { CHECK_EQ(504, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3448,7 +3427,7 @@ TEST(DebugStepForIn) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3486,7 +3465,7 @@ TEST(DebugStepForIn) { CHECK_EQ(8, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3496,7 +3475,7 @@ TEST(DebugStepWith) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3517,7 +3496,7 @@ TEST(DebugStepWith) { CHECK_EQ(4, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3527,7 +3506,7 @@ TEST(DebugConditional) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3553,7 +3532,7 @@ TEST(DebugConditional) { CHECK_EQ(5, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3568,7 +3547,7 @@ TEST(StepInOutSimple) { "frame_function_name"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStepSequence); + v8::Debug::SetDebugEventListener2(DebugEventStepSequence); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3604,7 +3583,7 @@ TEST(StepInOutSimple) { break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3619,7 +3598,7 @@ TEST(StepInOutTree) { "frame_function_name"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStepSequence); + v8::Debug::SetDebugEventListener2(DebugEventStepSequence); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3656,7 +3635,7 @@ TEST(StepInOutTree) { break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(true); } @@ -3671,7 +3650,7 @@ TEST(StepInOutBranch) { "frame_function_name"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStepSequence); + v8::Debug::SetDebugEventListener2(DebugEventStepSequence); // Create a function for testing stepping. Run it to allow it to get // optimized. @@ -3691,7 +3670,7 @@ TEST(StepInOutBranch) { break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3708,7 +3687,7 @@ TEST(DebugStepNatives) { "foo"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); step_action = StepIn; break_point_hit_count = 0; @@ -3717,11 +3696,11 @@ TEST(DebugStepNatives) { // With stepping all break locations are hit. CHECK_EQ(3, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Register a debug event listener which just counts. - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); @@ -3729,7 +3708,7 @@ TEST(DebugStepNatives) { // Without stepping only active break points are hit. CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3747,7 +3726,7 @@ TEST(DebugStepFunctionApply) { "foo"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); step_action = StepIn; break_point_hit_count = 0; @@ -3756,11 +3735,11 @@ TEST(DebugStepFunctionApply) { // With stepping all break locations are hit. CHECK_EQ(7, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Register a debug event listener which just counts. - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); @@ -3768,7 +3747,7 @@ TEST(DebugStepFunctionApply) { // Without stepping only the debugger statement is hit. CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3792,7 +3771,7 @@ TEST(DebugStepFunctionCall) { "foo"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStep); + v8::Debug::SetDebugEventListener2(DebugEventStep); step_action = StepIn; // Check stepping where the if condition in bar is false. @@ -3807,11 +3786,11 @@ TEST(DebugStepFunctionCall) { foo->Call(env->Global(), argc, argv); CHECK_EQ(8, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); // Register a debug event listener which just counts. - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); @@ -3819,7 +3798,7 @@ TEST(DebugStepFunctionCall) { // Without stepping only the debugger statement is hit. CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3831,7 +3810,7 @@ TEST(PauseInScript) { env.ExposeDebug(); // Register a debug event listener which counts. - v8::Debug::SetDebugEventListener(DebugEventCounter); + v8::Debug::SetDebugEventListener2(DebugEventCounter); // Create a script that returns a function. const char* src = "(function (evt) {})"; @@ -3850,7 +3829,7 @@ TEST(PauseInScript) { CHECK_EQ(1, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -3878,7 +3857,7 @@ TEST(BreakOnException) { CompileFunction(&env, "function notCaught(){throws();}", "notCaught"); v8::V8::AddMessageListener(MessageCallbackCount); - v8::Debug::SetDebugEventListener(DebugEventCounter); + v8::Debug::SetDebugEventListener2(DebugEventCounter); // Initial state should be no break on exceptions. DebugEventCounterClear(); @@ -3996,7 +3975,7 @@ TEST(BreakOnException) { CHECK_EQ(1, uncaught_exception_hit_count); CHECK_EQ(1, message_callback_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); v8::V8::RemoveMessageListeners(MessageCallbackCount); } @@ -4018,7 +3997,7 @@ TEST(BreakOnCompileException) { frame_count = CompileFunction(&env, frame_count_source, "frame_count"); v8::V8::AddMessageListener(MessageCallbackCount); - v8::Debug::SetDebugEventListener(DebugEventCounter); + v8::Debug::SetDebugEventListener2(DebugEventCounter); DebugEventCounterClear(); MessageCallbackCountClear(); @@ -4072,7 +4051,7 @@ TEST(StepWithException) { "frame_function_name"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventStepSequence); + v8::Debug::SetDebugEventListener2(DebugEventStepSequence); // Create functions for testing stepping. const char* src = "function a() { n(); }; " @@ -4144,7 +4123,7 @@ TEST(StepWithException) { break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -4158,7 +4137,7 @@ TEST(DebugBreak) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which sets the break flag and counts. - v8::Debug::SetDebugEventListener(DebugEventBreak); + v8::Debug::SetDebugEventListener2(DebugEventBreak); // Create a function for testing stepping. const char* src = "function f0() {}" @@ -4198,7 +4177,7 @@ TEST(DebugBreak) { CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -4210,7 +4189,7 @@ TEST(DisableBreak) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which sets the break flag and counts. - v8::Debug::SetDebugEventListener(DebugEventCounter); + v8::Debug::SetDebugEventListener2(DebugEventCounter); // Create a function for testing stepping. const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}"; @@ -4226,7 +4205,8 @@ TEST(DisableBreak) { { v8::Debug::DebugBreak(); - v8::internal::DisableBreak disable_break(true); + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate()); + v8::internal::DisableBreak disable_break(isolate, true); f->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); } @@ -4235,7 +4215,7 @@ TEST(DisableBreak) { CHECK_EQ(2, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -4251,7 +4231,7 @@ TEST(NoBreakWhenBootstrapping) { v8::HandleScope scope(isolate); // Register a debug event listener which sets the break flag and counts. - v8::Debug::SetDebugEventListener(DebugEventCounter); + v8::Debug::SetDebugEventListener2(DebugEventCounter); // Set the debug break flag. v8::Debug::DebugBreak(); @@ -4270,7 +4250,7 @@ TEST(NoBreakWhenBootstrapping) { CHECK_EQ(0, break_point_hit_count); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -4695,82 +4675,62 @@ TEST(NoHiddenProperties) { // Support classes -// Provides synchronization between k threads, where k is an input to the -// constructor. The Wait() call blocks a thread until it is called for the -// k'th time, then all calls return. Each ThreadBarrier object can only -// be used once. -class ThreadBarrier { +// Provides synchronization between N threads, where N is a template parameter. +// The Wait() call blocks a thread until it is called for the Nth time, then all +// calls return. Each ThreadBarrier object can only be used once. +template <int N> +class ThreadBarrier V8_FINAL { public: - explicit ThreadBarrier(int num_threads); - ~ThreadBarrier(); - void Wait(); - private: - int num_threads_; - int num_blocked_; - v8::internal::Mutex* lock_; - v8::internal::Semaphore* sem_; - bool invalid_; -}; + ThreadBarrier() : num_blocked_(0) {} -ThreadBarrier::ThreadBarrier(int num_threads) - : num_threads_(num_threads), num_blocked_(0) { - lock_ = OS::CreateMutex(); - sem_ = OS::CreateSemaphore(0); - invalid_ = false; // A barrier may only be used once. Then it is invalid. -} + ~ThreadBarrier() { + LockGuard<Mutex> lock_guard(&mutex_); + if (num_blocked_ != 0) { + CHECK_EQ(N, num_blocked_); + } + } + void Wait() { + LockGuard<Mutex> lock_guard(&mutex_); + CHECK_LT(num_blocked_, N); + num_blocked_++; + if (N == num_blocked_) { + // Signal and unblock all waiting threads. + cv_.NotifyAll(); + printf("BARRIER\n\n"); + fflush(stdout); + } else { // Wait for the semaphore. + while (num_blocked_ < N) { + cv_.Wait(&mutex_); + } + } + CHECK_EQ(N, num_blocked_); + } -// Do not call, due to race condition with Wait(). -// Could be resolved with Pthread condition variables. -ThreadBarrier::~ThreadBarrier() { - lock_->Lock(); - delete lock_; - delete sem_; -} + private: + ConditionVariable cv_; + Mutex mutex_; + int num_blocked_; + STATIC_CHECK(N > 0); -void ThreadBarrier::Wait() { - lock_->Lock(); - CHECK(!invalid_); - if (num_blocked_ == num_threads_ - 1) { - // Signal and unblock all waiting threads. - for (int i = 0; i < num_threads_ - 1; ++i) { - sem_->Signal(); - } - invalid_ = true; - printf("BARRIER\n\n"); - fflush(stdout); - lock_->Unlock(); - } else { // Wait for the semaphore. - ++num_blocked_; - lock_->Unlock(); // Potential race condition with destructor because - sem_->Wait(); // these two lines are not atomic. - } -} + DISALLOW_COPY_AND_ASSIGN(ThreadBarrier); +}; // A set containing enough barriers and semaphores for any of the tests. class Barriers { public: - Barriers(); - void Initialize(); - ThreadBarrier barrier_1; - ThreadBarrier barrier_2; - ThreadBarrier barrier_3; - ThreadBarrier barrier_4; - ThreadBarrier barrier_5; - v8::internal::Semaphore* semaphore_1; - v8::internal::Semaphore* semaphore_2; + Barriers() : semaphore_1(0), semaphore_2(0) {} + ThreadBarrier<2> barrier_1; + ThreadBarrier<2> barrier_2; + ThreadBarrier<2> barrier_3; + ThreadBarrier<2> barrier_4; + ThreadBarrier<2> barrier_5; + v8::internal::Semaphore semaphore_1; + v8::internal::Semaphore semaphore_2; }; -Barriers::Barriers() : barrier_1(2), barrier_2(2), - barrier_3(2), barrier_4(2), barrier_5(2) {} - -void Barriers::Initialize() { - semaphore_1 = OS::CreateSemaphore(0); - semaphore_2 = OS::CreateSemaphore(0); -} - // We match parts of the message to decide if it is a break message. bool IsBreakEventMessage(char *message) { @@ -4875,19 +4835,19 @@ class MessageQueueDebuggerThread : public v8::internal::Thread { void Run(); }; -static void MessageHandler(const uint16_t* message, int length, - v8::Debug::ClientData* client_data) { - static char print_buffer[1000]; - Utf16ToAscii(message, length, print_buffer); - if (IsBreakEventMessage(print_buffer)) { + +static void MessageHandler(const v8::Debug::Message& message) { + v8::Handle<v8::String> json = message.GetJSON(); + v8::String::AsciiValue ascii(json); + if (IsBreakEventMessage(*ascii)) { // Lets test script wait until break occurs to send commands. // Signals when a break is reported. - message_queue_barriers.semaphore_2->Signal(); + message_queue_barriers.semaphore_2.Signal(); } // Allow message handler to block on a semaphore, to test queueing of // messages while blocked. - message_queue_barriers.semaphore_1->Wait(); + message_queue_barriers.semaphore_1.Wait(); } @@ -4922,7 +4882,7 @@ void MessageQueueDebuggerThread::Run() { /* Interleaved sequence of actions by the two threads:*/ // Main thread compiles and runs source_1 - message_queue_barriers.semaphore_1->Signal(); + message_queue_barriers.semaphore_1.Signal(); message_queue_barriers.barrier_1.Wait(); // Post 6 commands, filling the command queue and making it expand. // These calls return immediately, but the commands stay on the queue @@ -4943,15 +4903,15 @@ void MessageQueueDebuggerThread::Run() { // All the commands added so far will fail to execute as long as call stack // is empty on beforeCompile event. for (int i = 0; i < 6 ; ++i) { - message_queue_barriers.semaphore_1->Signal(); + message_queue_barriers.semaphore_1.Signal(); } message_queue_barriers.barrier_3.Wait(); // Main thread compiles and runs source_3. // Don't stop in the afterCompile handler. - message_queue_barriers.semaphore_1->Signal(); + message_queue_barriers.semaphore_1.Signal(); // source_3 includes a debugger statement, which causes a break event. // Wait on break event from hitting "debugger" statement - message_queue_barriers.semaphore_2->Wait(); + message_queue_barriers.semaphore_2.Wait(); // These should execute after the "debugger" statement in source_2 v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_1, buffer_1)); v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_2, buffer_2)); @@ -4959,15 +4919,15 @@ void MessageQueueDebuggerThread::Run() { v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_single_step, buffer_2)); // Run after 2 break events, 4 responses. for (int i = 0; i < 6 ; ++i) { - message_queue_barriers.semaphore_1->Signal(); + message_queue_barriers.semaphore_1.Signal(); } // Wait on break event after a single step executes. - message_queue_barriers.semaphore_2->Wait(); + message_queue_barriers.semaphore_2.Wait(); v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_2, buffer_1)); v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_continue, buffer_2)); // Run after 2 responses. for (int i = 0; i < 2 ; ++i) { - message_queue_barriers.semaphore_1->Signal(); + message_queue_barriers.semaphore_1.Signal(); } // Main thread continues running source_3 to end, waits for this thread. } @@ -4980,8 +4940,7 @@ TEST(MessageQueues) { // Create a V8 environment DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - message_queue_barriers.Initialize(); - v8::Debug::SetMessageHandler(MessageHandler); + v8::Debug::SetMessageHandler2(MessageHandler); message_queue_debugger_thread.Start(); const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;"; @@ -5216,8 +5175,6 @@ TEST(ThreadedDebugging) { V8Thread v8_thread; // Create a V8 environment - threaded_debugging_barriers.Initialize(); - v8_thread.Start(); debugger_thread.Start(); @@ -5263,10 +5220,10 @@ static void BreakpointsMessageHandler(const v8::Debug::Message& message) { if (IsBreakEventMessage(print_buffer)) { break_event_breakpoint_id = GetBreakpointIdFromBreakEventMessage(print_buffer); - breakpoints_barriers->semaphore_1->Signal(); + breakpoints_barriers->semaphore_1.Signal(); } else if (IsEvaluateResponseMessage(print_buffer)) { evaluate_int_result = GetEvaluateIntResult(print_buffer); - breakpoints_barriers->semaphore_1->Signal(); + breakpoints_barriers->semaphore_1.Signal(); } } @@ -5375,42 +5332,42 @@ void BreakpointsDebuggerThread::Run() { breakpoints_barriers->barrier_2.Wait(); // V8 thread starts compiling source_2. // Automatic break happens, to run queued commands - // breakpoints_barriers->semaphore_1->Wait(); + // breakpoints_barriers->semaphore_1.Wait(); // Commands 1 through 3 run, thread continues. // v8 thread runs source_2 to breakpoint in cat(). // message callback receives break event. - breakpoints_barriers->semaphore_1->Wait(); + breakpoints_barriers->semaphore_1.Wait(); // Must have hit breakpoint #1. CHECK_EQ(1, break_event_breakpoint_id); // 4:Evaluate dog() (which has a breakpoint). v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer)); // V8 thread hits breakpoint in dog(). - breakpoints_barriers->semaphore_1->Wait(); // wait for break event + breakpoints_barriers->semaphore_1.Wait(); // wait for break event // Must have hit breakpoint #2. CHECK_EQ(2, break_event_breakpoint_id); // 5:Evaluate (x + 1). v8::Debug::SendCommand(buffer, AsciiToUtf16(command_4, buffer)); // Evaluate (x + 1) finishes. - breakpoints_barriers->semaphore_1->Wait(); + breakpoints_barriers->semaphore_1.Wait(); // Must have result 108. CHECK_EQ(108, evaluate_int_result); // 6:Continue evaluation of dog(). v8::Debug::SendCommand(buffer, AsciiToUtf16(command_5, buffer)); // Evaluate dog() finishes. - breakpoints_barriers->semaphore_1->Wait(); + breakpoints_barriers->semaphore_1.Wait(); // Must have result 107. CHECK_EQ(107, evaluate_int_result); // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint // in cat(19). v8::Debug::SendCommand(buffer, AsciiToUtf16(command_6, buffer)); // Message callback gets break event. - breakpoints_barriers->semaphore_1->Wait(); // wait for break event + breakpoints_barriers->semaphore_1.Wait(); // wait for break event // Must have hit breakpoint #1. CHECK_EQ(1, break_event_breakpoint_id); // 8: Evaluate dog() with breaks disabled. v8::Debug::SendCommand(buffer, AsciiToUtf16(command_7, buffer)); // Evaluate dog() finishes. - breakpoints_barriers->semaphore_1->Wait(); + breakpoints_barriers->semaphore_1.Wait(); // Must have result 116. CHECK_EQ(116, evaluate_int_result); // 9: Continue evaluation of source2, reach end. @@ -5426,7 +5383,6 @@ void TestRecursiveBreakpointsGeneric(bool global_evaluate) { // Create a V8 environment Barriers stack_allocated_breakpoints_barriers; - stack_allocated_breakpoints_barriers.Initialize(); breakpoints_barriers = &stack_allocated_breakpoints_barriers; breakpoints_v8_thread.Start(); @@ -5447,15 +5403,13 @@ TEST(RecursiveBreakpointsGlobal) { } -static void DummyDebugEventListener(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DummyDebugEventListener( + const v8::Debug::EventDetails& event_details) { } TEST(SetDebugEventListenerOnUninitializedVM) { - v8::Debug::SetDebugEventListener(DummyDebugEventListener); + v8::Debug::SetDebugEventListener2(DummyDebugEventListener); } @@ -5646,8 +5600,7 @@ TEST(DebuggerUnload) { // Set a debug event listener. break_point_hit_count = 0; - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); { v8::HandleScope scope(env->GetIsolate()); // Create a couple of functions for the test. @@ -5672,7 +5625,7 @@ TEST(DebuggerUnload) { // Remove the debug event listener without clearing breakpoints. Do this // outside a handle scope. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(true); // Now set a debug message handler. @@ -5750,7 +5703,7 @@ TEST(DebuggerClearMessageHandler) { // Clear debug message handler. message_handler_hit_count = 0; - v8::Debug::SetMessageHandler(NULL); + v8::Debug::SetMessageHandler2(NULL); // Run code to throw a unhandled exception. This should end up in the message // handler. @@ -5769,7 +5722,7 @@ static void MessageHandlerClearingMessageHandler( message_handler_hit_count++; // Clear debug message handler. - v8::Debug::SetMessageHandler(NULL); + v8::Debug::SetMessageHandler2(NULL); } @@ -5822,7 +5775,7 @@ static void HostDispatchMessageHandler(const v8::Debug::Message& message) { static void HostDispatchDispatchHandler() { - host_dispatch_barriers->semaphore_1->Signal(); + host_dispatch_barriers->semaphore_1.Signal(); } @@ -5874,7 +5827,7 @@ void HostDispatchDebuggerThread::Run() { // v8 thread starts compiling source_2. // Break happens, to run queued commands and host dispatches. // Wait for host dispatch to be processed. - host_dispatch_barriers->semaphore_1->Wait(); + host_dispatch_barriers->semaphore_1.Wait(); // 2: Continue evaluation v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer)); } @@ -5887,7 +5840,6 @@ TEST(DebuggerHostDispatch) { // Create a V8 environment Barriers stack_allocated_host_dispatch_barriers; - stack_allocated_host_dispatch_barriers.Initialize(); host_dispatch_barriers = &stack_allocated_host_dispatch_barriers; host_dispatch_v8_thread.Start(); @@ -5921,7 +5873,7 @@ Barriers* debug_message_dispatch_barriers; static void DebugMessageHandler() { - debug_message_dispatch_barriers->semaphore_1->Signal(); + debug_message_dispatch_barriers->semaphore_1.Signal(); } @@ -5935,7 +5887,7 @@ void DebugMessageDispatchV8Thread::Run() { CompileRun("var y = 1 + 2;\n"); debug_message_dispatch_barriers->barrier_1.Wait(); - debug_message_dispatch_barriers->semaphore_1->Wait(); + debug_message_dispatch_barriers->semaphore_1.Wait(); debug_message_dispatch_barriers->barrier_2.Wait(); } @@ -5955,7 +5907,6 @@ TEST(DebuggerDebugMessageDispatch) { // Create a V8 environment Barriers stack_allocated_debug_message_dispatch_barriers; - stack_allocated_debug_message_dispatch_barriers.Initialize(); debug_message_dispatch_barriers = &stack_allocated_debug_message_dispatch_barriers; @@ -5983,9 +5934,6 @@ TEST(DebuggerAgent) { bool ok; - // Initialize the socket library. - i::Socket::SetUp(); - // Test starting and stopping the agent without any client connection. debugger->StartAgent("test", kPort1); debugger->StopAgent(); @@ -5994,7 +5942,7 @@ TEST(DebuggerAgent) { ok = debugger->StartAgent("test", kPort2); CHECK(ok); debugger->WaitForAgent(); - i::Socket* client = i::OS::CreateSocket(); + i::Socket* client = new i::Socket; ok = client->Connect("localhost", port2_str); CHECK(ok); // It is important to wait for a message from the agent. Otherwise, @@ -6008,8 +5956,9 @@ TEST(DebuggerAgent) { // Test starting and stopping the agent with the required port already // occoupied. - i::Socket* server = i::OS::CreateSocket(); - server->Bind(kPort3); + i::Socket* server = new i::Socket; + ok = server->Bind(kPort3); + CHECK(ok); debugger->StartAgent("test", kPort3); debugger->StopAgent(); @@ -6025,17 +5974,16 @@ class DebuggerAgentProtocolServerThread : public i::Thread { port_(port), server_(NULL), client_(NULL), - listening_(OS::CreateSemaphore(0)) { + listening_(0) { } ~DebuggerAgentProtocolServerThread() { // Close both sockets. delete client_; delete server_; - delete listening_; } void Run(); - void WaitForListening() { listening_->Wait(); } + void WaitForListening() { listening_.Wait(); } char* body() { return *body_; } private: @@ -6043,7 +5991,7 @@ class DebuggerAgentProtocolServerThread : public i::Thread { i::SmartArrayPointer<char> body_; i::Socket* server_; // Server socket used for bind/accept. i::Socket* client_; // Single client connection used by the test. - i::Semaphore* listening_; // Signalled when the server is in listen mode. + i::Semaphore listening_; // Signalled when the server is in listen mode. }; @@ -6051,7 +5999,7 @@ void DebuggerAgentProtocolServerThread::Run() { bool ok; // Create the server socket and bind it to the requested port. - server_ = i::OS::CreateSocket(); + server_ = new i::Socket; CHECK(server_ != NULL); ok = server_->Bind(port_); CHECK(ok); @@ -6059,7 +6007,7 @@ void DebuggerAgentProtocolServerThread::Run() { // Listen for new connections. ok = server_->Listen(1); CHECK(ok); - listening_->Signal(); + listening_.Signal(); // Accept a connection. client_ = server_->Accept(); @@ -6081,9 +6029,6 @@ TEST(DebuggerAgentProtocolOverflowHeader) { char port_str[kPortBufferLen]; OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort); - // Initialize the socket library. - i::Socket::SetUp(); - // Create a socket server to receive a debugger agent message. DebuggerAgentProtocolServerThread* server = new DebuggerAgentProtocolServerThread(kPort); @@ -6091,7 +6036,7 @@ TEST(DebuggerAgentProtocolOverflowHeader) { server->WaitForListening(); // Connect. - i::Socket* client = i::OS::CreateSocket(); + i::Socket* client = new i::Socket; CHECK(client != NULL); bool ok = client->Connect(kLocalhost, port_str); CHECK(ok); @@ -6108,7 +6053,8 @@ TEST(DebuggerAgentProtocolOverflowHeader) { buffer[kBufferSize - 3] = '0'; buffer[kBufferSize - 2] = '\r'; buffer[kBufferSize - 1] = '\n'; - client->Send(buffer, kBufferSize); + int result = client->Send(buffer, kBufferSize); + CHECK_EQ(kBufferSize, result); // Short key and long value: X:XXXX....XXXX\r\n. buffer[0] = 'X'; @@ -6118,13 +6064,16 @@ TEST(DebuggerAgentProtocolOverflowHeader) { } buffer[kBufferSize - 2] = '\r'; buffer[kBufferSize - 1] = '\n'; - client->Send(buffer, kBufferSize); + result = client->Send(buffer, kBufferSize); + CHECK_EQ(kBufferSize, result); // Add empty body to request. const char* content_length_zero_header = "Content-Length:0\r\n"; - client->Send(content_length_zero_header, - StrLength(content_length_zero_header)); - client->Send("\r\n", 2); + int length = StrLength(content_length_zero_header); + result = client->Send(content_length_zero_header, length); + CHECK_EQ(length, result); + result = client->Send("\r\n", 2); + CHECK_EQ(2, result); // Wait until data is received. server->Join(); @@ -6203,8 +6152,7 @@ TEST(ScriptNameAndData) { compiled_script_data_source, "compiled_script_data"); - v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount); // Test function source. v8::Local<v8::String> script = v8::String::New( @@ -6391,10 +6339,9 @@ TEST(DebugBreakInMessageHandler) { // Debug event handler which gets the function on the top frame and schedules a // break a number of times. static void DebugEventDebugBreak( - v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); if (event == v8::Break) { break_point_hit_count++; @@ -6445,7 +6392,7 @@ TEST(RegExpDebugBreak) { v8::Local<v8::Value> result = f->Call(env->Global(), argc, argv); CHECK_EQ(12, result->Int32Value()); - v8::Debug::SetDebugEventListener(DebugEventDebugBreak); + v8::Debug::SetDebugEventListener2(DebugEventDebugBreak); v8::Debug::DebugBreak(); result = f->Call(env->Global(), argc, argv); @@ -6576,10 +6523,9 @@ TEST(NestedBreakEventContextData) { // Debug event listener which counts the script collected events. int script_collected_count = 0; -static void DebugEventScriptCollectedEvent(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventScriptCollectedEvent( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); // Count the number of breaks. if (event == v8::ScriptCollected) { script_collected_count++; @@ -6603,8 +6549,7 @@ TEST(ScriptCollectedEvent) { HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); script_collected_count = 0; - v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventScriptCollectedEvent); { v8::Script::Compile(v8::String::New("eval('a=1')"))->Run(); v8::Script::Compile(v8::String::New("eval('a=2')"))->Run(); @@ -6616,7 +6561,7 @@ TEST(ScriptCollectedEvent) { CHECK_EQ(2, script_collected_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -6676,7 +6621,7 @@ TEST(ScriptCollectedEventContext) { v8::Local<v8::Context>::New(isolate, context); local_context->Exit(); } - context.Dispose(isolate); + context.Dispose(); // Do garbage collection to collect the script above which is no longer // referenced. @@ -7017,7 +6962,7 @@ TEST(DebugBreakFunctionApply) { "foo"); // Register a debug event listener which steps and counts. - v8::Debug::SetDebugEventListener(DebugEventBreakMax); + v8::Debug::SetDebugEventListener2(DebugEventBreakMax); // Set the debug break flag before calling the code using function.apply. v8::Debug::DebugBreak(); @@ -7031,7 +6976,7 @@ TEST(DebugBreakFunctionApply) { // When keeping the debug break several break will happen. CHECK_GT(break_point_hit_count, 1); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } @@ -7060,10 +7005,9 @@ static void NamedGetterWithCallingContextCheck( // an object with property 'a' == 1. If the property has custom accessor // this handler will eventually invoke it. static void DebugEventGetAtgumentPropertyValue( - v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); if (event == v8::Break) { break_point_hit_count++; CHECK(debugger_context == v8::Context::GetCurrent()); @@ -7100,7 +7044,7 @@ TEST(CallingContextIsNotDebugContext) { named->NewInstance()); // Register the debug event listener - v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue); + v8::Debug::SetDebugEventListener2(DebugEventGetAtgumentPropertyValue); // Create a function that invokes debugger. v8::Local<v8::Function> foo = CompileFunction( @@ -7113,7 +7057,7 @@ TEST(CallingContextIsNotDebugContext) { foo->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); debugee_context = v8::Handle<v8::Context>(); debugger_context = v8::Handle<v8::Context>(); CheckDebuggerUnloaded(); @@ -7146,7 +7090,7 @@ TEST(DebugEventContext) { v8::Context::Scope context_scope(expected_context); v8::Script::Compile(v8::String::New("(function(){debugger;})();"))->Run(); expected_context.Clear(); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); expected_context_data = v8::Handle<v8::Value>(); CheckDebuggerUnloaded(); } @@ -7213,16 +7157,16 @@ TEST(DebugEventBreakData) { CHECK_EQ(TestClientData::constructor_call_counter, TestClientData::destructor_call_counter); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } static bool debug_event_break_deoptimize_done = false; -static void DebugEventBreakDeoptimize(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventBreakDeoptimize( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); if (event == v8::Break) { if (!frame_function_name.IsEmpty()) { // Get the name of the function. @@ -7265,8 +7209,7 @@ TEST(DeoptimizeDuringDebugBreak) { // This tests lazy deoptimization bailout for the stack check, as the first // time in function bar when using debug break and no break points will be at // the initial stack check. - v8::Debug::SetDebugEventListener(DebugEventBreakDeoptimize, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakDeoptimize); // Compile and run function bar which will optimize it for some flag settings. v8::Script::Compile(v8::String::New("function bar(){}; bar()"))->Run(); @@ -7277,14 +7220,14 @@ TEST(DeoptimizeDuringDebugBreak) { CHECK(debug_event_break_deoptimize_done); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); } -static void DebugEventBreakWithOptimizedStack(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventBreakWithOptimizedStack( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); + v8::Handle<v8::Object> exec_state = event_details.GetExecutionState(); if (event == v8::Break) { if (!frame_function_name.IsEmpty()) { for (int i = 0; i < 2; i++) { @@ -7329,8 +7272,7 @@ static void DebugEventBreakWithOptimizedStack(v8::DebugEvent event, static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack, - v8::Undefined()); + v8::Debug::SetDebugEventListener2(DebugEventBreakWithOptimizedStack); v8::Debug::DebugBreak(); } @@ -7413,7 +7355,7 @@ TEST(DebugBreakLoop) { v8::HandleScope scope(env->GetIsolate()); // Register a debug event listener which sets the break flag and counts. - v8::Debug::SetDebugEventListener(DebugEventBreakMax); + v8::Debug::SetDebugEventListener2(DebugEventBreakMax); // Create a function for getting the frame count when hitting the break. frame_count = CompileFunction(&env, frame_count_source, "frame_count"); @@ -7447,17 +7389,16 @@ TEST(DebugBreakLoop) { TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}"); // Get rid of the debug event listener. - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CheckDebuggerUnloaded(); } v8::Local<v8::Script> inline_script; -static void DebugBreakInlineListener(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugBreakInlineListener( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); if (event != v8::Break) return; int expected_frame_count = 4; @@ -7484,7 +7425,7 @@ static void DebugBreakInlineListener(v8::DebugEvent event, CHECK_EQ(expected_line_number[i], i::GetScriptLineNumber(source_script, result->Int32Value())); } - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); v8::V8::TerminateExecution(); } @@ -7507,16 +7448,15 @@ TEST(DebugBreakInline) { "g(false); \n" "%OptimizeFunctionOnNextCall(g); \n" "g(true);"; - v8::Debug::SetDebugEventListener(DebugBreakInlineListener); + v8::Debug::SetDebugEventListener2(DebugBreakInlineListener); inline_script = v8::Script::Compile(v8::String::New(source)); inline_script->Run(); } -static void DebugEventStepNext(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void DebugEventStepNext( + const v8::Debug::EventDetails& event_details) { + v8::DebugEvent event = event_details.GetEvent(); if (event == v8::Break) { PrepareStep(StepNext); } @@ -7541,7 +7481,7 @@ TEST(Regress131642) { // on the stack. DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetDebugEventListener(DebugEventStepNext); + v8::Debug::SetDebugEventListener2(DebugEventStepNext); // We step through the first script. It exits through an exception. We run // this inside a new frame to record a different FP than the second script @@ -7553,7 +7493,7 @@ TEST(Regress131642) { const char* script_2 = "[0].forEach(function() { });"; CompileRun(script_2); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); } @@ -7561,10 +7501,7 @@ TEST(Regress131642) { int CountNativeContexts(); -static void NopListener(v8::DebugEvent event, - v8::Handle<v8::Object> exec_state, - v8::Handle<v8::Object> event_data, - v8::Handle<v8::Value> data) { +static void NopListener(const v8::Debug::EventDetails& event_details) { } @@ -7573,15 +7510,15 @@ TEST(DebuggerCreatesContextIffActive) { v8::HandleScope scope(env->GetIsolate()); CHECK_EQ(1, CountNativeContexts()); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); CompileRun("debugger;"); CHECK_EQ(1, CountNativeContexts()); - v8::Debug::SetDebugEventListener(NopListener); + v8::Debug::SetDebugEventListener2(NopListener); CompileRun("debugger;"); CHECK_EQ(2, CountNativeContexts()); - v8::Debug::SetDebugEventListener(NULL); + v8::Debug::SetDebugEventListener2(NULL); } diff --git a/deps/v8/test/cctest/test-declarative-accessors.cc b/deps/v8/test/cctest/test-declarative-accessors.cc index 2d2f5cd23b..fa5a0452fd 100644 --- a/deps/v8/test/cctest/test-declarative-accessors.cc +++ b/deps/v8/test/cctest/test-declarative-accessors.cc @@ -38,11 +38,11 @@ class HandleArray : public Malloced { public: static const unsigned kArraySize = 200; explicit HandleArray() {} - ~HandleArray() { Reset(v8::Isolate::GetCurrent()); } - void Reset(v8::Isolate* isolate) { + ~HandleArray() { Reset(); } + void Reset() { for (unsigned i = 0; i < kArraySize; i++) { if (handles_[i].IsEmpty()) continue; - handles_[i].Dispose(isolate); + handles_[i].Dispose(); handles_[i].Clear(); } } @@ -101,7 +101,7 @@ static v8::Local<v8::ObjectTemplate> CreateConstructor( // Setup object template. if (descriptor_name != NULL && !descriptor.IsEmpty()) { bool added_accessor = - obj_template->SetAccessor(v8_str(descriptor_name), descriptor); + obj_template->SetDeclaredAccessor(v8_str(descriptor_name), descriptor); CHECK(added_accessor); } obj_template->SetInternalFieldCount((internal_field+1)*2 + 7); @@ -124,9 +124,9 @@ static void VerifyRead(v8::Handle<v8::DeclaredAccessorDescriptor> descriptor, context->Global()->Get(v8_str("accessible"))); obj->SetAlignedPointerInInternalField(internal_field, internal_object); bool added_accessor; - added_accessor = obj->SetAccessor(v8_str("y"), descriptor); + added_accessor = obj->SetDeclaredAccessor(v8_str("y"), descriptor); CHECK(added_accessor); - added_accessor = obj->SetAccessor(v8_str("13"), descriptor); + added_accessor = obj->SetDeclaredAccessor(v8_str("13"), descriptor); CHECK(added_accessor); // Test access from template getter. v8::Local<v8::Value> value; diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc index 0f6bb8fff7..18f142061b 100644 --- a/deps/v8/test/cctest/test-decls.cc +++ b/deps/v8/test/cctest/test-decls.cc @@ -56,7 +56,7 @@ class DeclarationContext { HandleScope scope(isolate); Local<Context> context = Local<Context>::New(isolate, context_); context->Exit(); - context_.Dispose(isolate); + context_.Dispose(); } } diff --git a/deps/v8/test/cctest/test-deoptimization.cc b/deps/v8/test/cctest/test-deoptimization.cc index c164193ee5..83a6354b2f 100644 --- a/deps/v8/test/cctest/test-deoptimization.cc +++ b/deps/v8/test/cctest/test-deoptimization.cc @@ -77,27 +77,27 @@ class AlwaysOptimizeAllowNativesSyntaxNoInlining { // Utility class to set --allow-natives-syntax and --nouse-inlining when // constructed and return to their default state when destroyed. -class AllowNativesSyntaxNoInliningNoParallel { +class AllowNativesSyntaxNoInliningNoConcurrent { public: - AllowNativesSyntaxNoInliningNoParallel() + AllowNativesSyntaxNoInliningNoConcurrent() : allow_natives_syntax_(i::FLAG_allow_natives_syntax), use_inlining_(i::FLAG_use_inlining), - parallel_recompilation_(i::FLAG_parallel_recompilation) { + concurrent_recompilation_(i::FLAG_concurrent_recompilation) { i::FLAG_allow_natives_syntax = true; i::FLAG_use_inlining = false; - i::FLAG_parallel_recompilation = false; + i::FLAG_concurrent_recompilation = false; } - ~AllowNativesSyntaxNoInliningNoParallel() { + ~AllowNativesSyntaxNoInliningNoConcurrent() { i::FLAG_allow_natives_syntax = allow_natives_syntax_; i::FLAG_use_inlining = use_inlining_; - i::FLAG_parallel_recompilation = parallel_recompilation_; + i::FLAG_concurrent_recompilation = concurrent_recompilation_; } private: bool allow_natives_syntax_; bool use_inlining_; - bool parallel_recompilation_; + bool concurrent_recompilation_; }; @@ -347,7 +347,7 @@ TEST(DeoptimizeBinaryOperationADDString) { const char* f_source = "function f(x, y) { return x + y; };"; { - AllowNativesSyntaxNoInliningNoParallel options; + AllowNativesSyntaxNoInliningNoConcurrent options; // Compile function f and collect to type feedback to insert binary op stub // call in the optimized code. i::FLAG_prepare_always_opt = true; @@ -367,7 +367,7 @@ TEST(DeoptimizeBinaryOperationADDString) { i::FLAG_always_opt = true; CompileRun(f_source); CompileRun("f('a+', new X());"); - CHECK(!i::V8::UseCrankshaft() || + CHECK(!i::Isolate::Current()->use_crankshaft() || GetJSFunction(env->Global(), "f")->IsOptimized()); // Call f and force deoptimization while processing the binary operation. @@ -405,7 +405,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env, binary_op); char* f_source = f_source_buffer.start(); - AllowNativesSyntaxNoInliningNoParallel options; + AllowNativesSyntaxNoInliningNoConcurrent options; // Compile function f and collect to type feedback to insert binary op stub // call in the optimized code. i::FLAG_prepare_always_opt = true; @@ -419,7 +419,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env, i::FLAG_always_opt = true; CompileRun(f_source); CompileRun("f(7, new X());"); - CHECK(!i::V8::UseCrankshaft() || + CHECK(!i::Isolate::Current()->use_crankshaft() || GetJSFunction((*env)->Global(), "f")->IsOptimized()); // Call f and force deoptimization while processing the binary operation. @@ -497,7 +497,7 @@ TEST(DeoptimizeCompare) { const char* f_source = "function f(x, y) { return x < y; };"; { - AllowNativesSyntaxNoInliningNoParallel options; + AllowNativesSyntaxNoInliningNoConcurrent options; // Compile function f and collect to type feedback to insert compare ic // call in the optimized code. i::FLAG_prepare_always_opt = true; @@ -517,7 +517,7 @@ TEST(DeoptimizeCompare) { i::FLAG_always_opt = true; CompileRun(f_source); CompileRun("f('a', new X());"); - CHECK(!i::V8::UseCrankshaft() || + CHECK(!i::Isolate::Current()->use_crankshaft() || GetJSFunction(env->Global(), "f")->IsOptimized()); // Call f and force deoptimization while processing the comparison. @@ -544,7 +544,7 @@ TEST(DeoptimizeLoadICStoreIC) { const char* g2_source = "function g2(x, y) { x[y] = 1; };"; { - AllowNativesSyntaxNoInliningNoParallel options; + AllowNativesSyntaxNoInliningNoConcurrent options; // Compile functions and collect to type feedback to insert ic // calls in the optimized code. i::FLAG_prepare_always_opt = true; @@ -587,7 +587,7 @@ TEST(DeoptimizeLoadICStoreIC) { CompileRun("g1(new X());"); CompileRun("f2(new X(), 'z');"); CompileRun("g2(new X(), 'z');"); - if (i::V8::UseCrankshaft()) { + if (i::Isolate::Current()->use_crankshaft()) { CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); @@ -624,7 +624,7 @@ TEST(DeoptimizeLoadICStoreICNested) { const char* g2_source = "function g2(x, y) { x[y] = 1; };"; { - AllowNativesSyntaxNoInliningNoParallel options; + AllowNativesSyntaxNoInliningNoConcurrent options; // Compile functions and collect to type feedback to insert ic // calls in the optimized code. i::FLAG_prepare_always_opt = true; @@ -671,7 +671,7 @@ TEST(DeoptimizeLoadICStoreICNested) { CompileRun("g1(new X());"); CompileRun("f2(new X(), 'z');"); CompileRun("g2(new X(), 'z');"); - if (i::V8::UseCrankshaft()) { + if (i::Isolate::Current()->use_crankshaft()) { CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); diff --git a/deps/v8/test/cctest/test-dictionary.cc b/deps/v8/test/cctest/test-dictionary.cc index 2bdf235524..b9e8b1ec06 100644 --- a/deps/v8/test/cctest/test-dictionary.cc +++ b/deps/v8/test/cctest/test-dictionary.cc @@ -72,7 +72,7 @@ TEST(ObjectHashTable) { // Keys should map back to their respective values and also should get // an identity hash code generated. for (int i = 0; i < 100; i++) { - Handle<JSObject> key = factory->NewJSArray(7); + Handle<JSReceiver> key = factory->NewJSArray(7); Handle<JSObject> value = factory->NewJSArray(11); table = PutIntoObjectHashTable(table, key, value); CHECK_EQ(table->NumberOfElements(), i + 1); @@ -84,7 +84,7 @@ TEST(ObjectHashTable) { // Keys never added to the map which already have an identity hash // code should not be found. for (int i = 0; i < 100; i++) { - Handle<JSObject> key = factory->NewJSArray(7); + Handle<JSReceiver> key = factory->NewJSArray(7); CHECK(key->GetIdentityHash(ALLOW_CREATION)->ToObjectChecked()->IsSmi()); CHECK_EQ(table->FindEntry(*key), ObjectHashTable::kNotFound); CHECK_EQ(table->Lookup(*key), HEAP->the_hole_value()); @@ -94,13 +94,64 @@ TEST(ObjectHashTable) { // Keys that don't have an identity hash should not be found and also // should not get an identity hash code generated. for (int i = 0; i < 100; i++) { - Handle<JSObject> key = factory->NewJSArray(7); + Handle<JSReceiver> key = factory->NewJSArray(7); CHECK_EQ(table->Lookup(*key), HEAP->the_hole_value()); CHECK_EQ(key->GetIdentityHash(OMIT_CREATION), HEAP->undefined_value()); } } +class ObjectHashTableTest: public ObjectHashTable { + public: + void insert(int entry, int key, int value) { + set(EntryToIndex(entry), Smi::FromInt(key)); + set(EntryToIndex(entry) + 1, Smi::FromInt(value)); + } + + int lookup(int key) { + return Smi::cast(Lookup(Smi::FromInt(key)))->value(); + } + + int capacity() { + return Capacity(); + } +}; + + +TEST(HashTableRehash) { + LocalContext context; + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + v8::HandleScope scope(context->GetIsolate()); + // Test almost filled table. + { + Handle<ObjectHashTable> table = factory->NewObjectHashTable(100); + ObjectHashTableTest* t = reinterpret_cast<ObjectHashTableTest*>(*table); + int capacity = t->capacity(); + for (int i = 0; i < capacity - 1; i++) { + t->insert(i, i * i, i); + } + t->Rehash(Smi::FromInt(0)); + for (int i = 0; i < capacity - 1; i++) { + CHECK_EQ(i, t->lookup(i * i)); + } + } + // Test half-filled table. + { + Handle<ObjectHashTable> table = factory->NewObjectHashTable(100); + ObjectHashTableTest* t = reinterpret_cast<ObjectHashTableTest*>(*table); + int capacity = t->capacity(); + for (int i = 0; i < capacity / 2; i++) { + t->insert(i, i * i, i); + } + t->Rehash(Smi::FromInt(0)); + for (int i = 0; i < capacity / 2; i++) { + CHECK_EQ(i, t->lookup(i * i)); + } + } +} + + #ifdef DEBUG TEST(ObjectHashSetCausesGC) { i::FLAG_stress_compaction = false; diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc index 14447b2c45..1b6af47233 100644 --- a/deps/v8/test/cctest/test-disasm-ia32.cc +++ b/deps/v8/test/cctest/test-disasm-ia32.cc @@ -99,16 +99,7 @@ TEST(DisasmIa320) { __ or_(edx, 3); __ xor_(edx, 3); __ nop(); - { - CHECK(CpuFeatures::IsSupported(CPUID)); - CpuFeatureScope fscope(&assm, CPUID); - __ cpuid(); - } - { - CHECK(CpuFeatures::IsSupported(RDTSC)); - CpuFeatureScope fscope(&assm, RDTSC); - __ rdtsc(); - } + __ cpuid(); __ movsx_b(edx, ecx); __ movsx_w(edx, ecx); __ movzx_b(edx, ecx); diff --git a/deps/v8/test/cctest/test-disasm-x64.cc b/deps/v8/test/cctest/test-disasm-x64.cc index 1c7f416392..1ff9fd336b 100644 --- a/deps/v8/test/cctest/test-disasm-x64.cc +++ b/deps/v8/test/cctest/test-disasm-x64.cc @@ -95,11 +95,6 @@ TEST(DisasmX64) { CpuFeatures::Scope fscope(CPUID); __ cpuid(); } - { - CHECK(CpuFeatures::IsSupported(RDTSC)); - CpuFeatures::Scope fscope(RDTSC); - __ rdtsc(); - } __ movsxbq(rdx, Operand(rcx, 0)); __ movsxwq(rdx, Operand(rcx, 0)); __ movzxbl(rdx, Operand(rcx, 0)); diff --git a/deps/v8/test/cctest/test-global-handles.cc b/deps/v8/test/cctest/test-global-handles.cc index 0b652db37b..1d33a8c86b 100644 --- a/deps/v8/test/cctest/test-global-handles.cc +++ b/deps/v8/test/cctest/test-global-handles.cc @@ -321,24 +321,26 @@ TEST(EternalHandles) { CcTest::InitializeVM(); Isolate* isolate = Isolate::Current(); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); - EternalHandles* eternals = isolate->eternal_handles(); + EternalHandles* eternal_handles = isolate->eternal_handles(); // Create a number of handles that will not be on a block boundary const int kArrayLength = 2048-1; int indices[kArrayLength]; + v8::Eternal<v8::Value> eternals[kArrayLength]; - CHECK_EQ(0, eternals->NumberOfHandles()); + CHECK_EQ(0, eternal_handles->NumberOfHandles()); for (int i = 0; i < kArrayLength; i++) { + indices[i] = -1; HandleScope scope(isolate); v8::Local<v8::Object> object = v8::Object::New(); object->Set(i, v8::Integer::New(i, v8_isolate)); - if (i % 2 == 0) { - // Create with internal api - indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object)); - } else { - // Create with external api - indices[i] = object.Eternalize(v8_isolate); - } + // Create with internal api + eternal_handles->Create( + isolate, *v8::Utils::OpenHandle(*object), &indices[i]); + // Create with external api + CHECK(eternals[i].IsEmpty()); + eternals[i].Set(v8_isolate, object); + CHECK(!eternals[i].IsEmpty()); } isolate->heap()->CollectAllAvailableGarbage(); @@ -346,21 +348,31 @@ TEST(EternalHandles) { for (int i = 0; i < kArrayLength; i++) { for (int j = 0; j < 2; j++) { HandleScope scope(isolate); - v8::Local<v8::Object> object; + v8::Local<v8::Value> local; if (j == 0) { // Test internal api - v8::Local<v8::Value> local = - v8::Utils::ToLocal(eternals->Get(indices[i])); - object = v8::Handle<v8::Object>::Cast(local); + local = v8::Utils::ToLocal(eternal_handles->Get(indices[i])); } else { // Test external api - object = v8::Local<v8::Object>::GetEternal(v8_isolate, indices[i]); + local = eternals[i].Get(v8_isolate); } + v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(local); v8::Local<v8::Value> value = object->Get(i); CHECK(value->IsInt32()); CHECK_EQ(i, value->Int32Value()); } } - CHECK_EQ(kArrayLength, eternals->NumberOfHandles()); + CHECK_EQ(2*kArrayLength, eternal_handles->NumberOfHandles()); + + // Create an eternal via the constructor + { + HandleScope scope(isolate); + v8::Local<v8::Object> object = v8::Object::New(); + v8::Eternal<v8::Object> eternal(v8_isolate, object); + CHECK(!eternal.IsEmpty()); + CHECK(object == eternal.Get(v8_isolate)); + } + + CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles()); } diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index e30fcc00c9..0cf9cdaedf 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -404,12 +404,57 @@ TEST(HeapSnapshotSlicedString) { const v8::HeapGraphNode* child_string = GetProperty(global, v8::HeapGraphEdge::kProperty, "child_string"); CHECK_NE(NULL, child_string); + CHECK_EQ(v8::HeapGraphNode::kSlicedString, child_string->GetType()); const v8::HeapGraphNode* parent = GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent"); CHECK_EQ(parent_string, parent); + heap_profiler->DeleteAllHeapSnapshots(); } +TEST(HeapSnapshotConsString) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); + global_template->SetInternalFieldCount(1); + LocalContext env(NULL, global_template); + v8::Handle<v8::Object> global_proxy = env->Global(); + v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>(); + CHECK_EQ(1, global->InternalFieldCount()); + + i::Factory* factory = i::Isolate::Current()->factory(); + i::Handle<i::String> first = + factory->NewStringFromAscii(i::CStrVector("0123456789")); + i::Handle<i::String> second = + factory->NewStringFromAscii(i::CStrVector("0123456789")); + i::Handle<i::String> cons_string = factory->NewConsString(first, second); + + global->SetInternalField(0, v8::ToApiHandle<v8::String>(cons_string)); + + v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler(); + const v8::HeapSnapshot* snapshot = + heap_profiler->TakeHeapSnapshot(v8_str("cons_strings")); + CHECK(ValidateSnapshot(snapshot)); + const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot); + + const v8::HeapGraphNode* string_node = + GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"); + CHECK_NE(NULL, string_node); + CHECK_EQ(v8::HeapGraphNode::kConsString, string_node->GetType()); + + const v8::HeapGraphNode* first_node = + GetProperty(string_node, v8::HeapGraphEdge::kInternal, "first"); + CHECK_EQ(v8::HeapGraphNode::kString, first_node->GetType()); + + const v8::HeapGraphNode* second_node = + GetProperty(string_node, v8::HeapGraphEdge::kInternal, "second"); + CHECK_EQ(v8::HeapGraphNode::kString, second_node->GetType()); + + heap_profiler->DeleteAllHeapSnapshots(); +} + + + TEST(HeapSnapshotInternalReferences) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); @@ -1201,11 +1246,11 @@ TEST(HeapSnapshotRetainedObjectInfo) { heap_profiler->SetWrapperClassInfoProvider( 2, TestRetainedObjectInfo::WrapperInfoCallback); v8::Persistent<v8::String> p_AAA(isolate, v8_str("AAA")); - p_AAA.SetWrapperClassId(isolate, 1); + p_AAA.SetWrapperClassId(1); v8::Persistent<v8::String> p_BBB(isolate, v8_str("BBB")); - p_BBB.SetWrapperClassId(isolate, 1); + p_BBB.SetWrapperClassId(1); v8::Persistent<v8::String> p_CCC(isolate, v8_str("CCC")); - p_CCC.SetWrapperClassId(isolate, 2); + p_CCC.SetWrapperClassId(2); CHECK_EQ(0, TestRetainedObjectInfo::instances.length()); const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(v8_str("retained")); @@ -1711,7 +1756,7 @@ bool HasWeakGlobalHandle() { static void PersistentHandleCallback(v8::Isolate* isolate, v8::Persistent<v8::Value>* handle, void*) { - handle->Dispose(isolate); + handle->Dispose(); } diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 1813470838..9d74011fde 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -82,16 +82,18 @@ TEST(HeapMaps) { static void CheckOddball(Isolate* isolate, Object* obj, const char* string) { CHECK(obj->IsOddball()); bool exc; + Handle<Object> handle(obj, isolate); Object* print_string = - *Execution::ToString(Handle<Object>(obj, isolate), &exc); + *Execution::ToString(isolate, handle, &exc); CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string))); } static void CheckSmi(Isolate* isolate, int value, const char* string) { bool exc; + Handle<Object> handle(Smi::FromInt(value), isolate); Object* print_string = - *Execution::ToString(Handle<Object>(Smi::FromInt(value), isolate), &exc); + *Execution::ToString(isolate, handle, &exc); CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string))); } @@ -100,8 +102,9 @@ static void CheckNumber(Isolate* isolate, double value, const char* string) { Object* obj = HEAP->NumberFromDouble(value)->ToObjectChecked(); CHECK(obj->IsNumber()); bool exc; + Handle<Object> handle(obj, isolate); Object* print_string = - *Execution::ToString(Handle<Object>(obj, isolate), &exc); + *Execution::ToString(isolate, handle, &exc); CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string))); } @@ -398,7 +401,7 @@ static void TestWeakGlobalHandleCallback(v8::Isolate* isolate, v8::Persistent<v8::Value>* handle, void* id) { if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true; - handle->Dispose(isolate); + handle->Dispose(); } @@ -765,7 +768,7 @@ TEST(JSArray) { // array[length] = name. array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(1), array->length()); - CHECK_EQ(array->GetElement(0), *name); + CHECK_EQ(array->GetElement(isolate, 0), *name); // Set array length with larger than smi value. Handle<Object> length = @@ -782,8 +785,8 @@ TEST(JSArray) { uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); - CHECK_EQ(array->GetElement(int_length), *name); - CHECK_EQ(array->GetElement(0), *name); + CHECK_EQ(array->GetElement(isolate, int_length), *name); + CHECK_EQ(array->GetElement(isolate, 0), *name); } @@ -814,8 +817,8 @@ TEST(JSObjectCopy) { Handle<JSObject> clone = Copy(obj); CHECK(!clone.is_identical_to(obj)); - CHECK_EQ(obj->GetElement(0), clone->GetElement(0)); - CHECK_EQ(obj->GetElement(1), clone->GetElement(1)); + CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 0)); + CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 1)); CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first)); CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); @@ -829,8 +832,8 @@ TEST(JSObjectCopy) { clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked(); clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked(); - CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); - CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); + CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 0)); + CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 1)); CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first)); CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second)); @@ -1332,7 +1335,7 @@ TEST(TestInternalWeakLists) { isolate->compilation_cache()->Clear(); heap->CollectAllGarbage(Heap::kNoGCFlags); - bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); + bool opt = (FLAG_always_opt && isolate->use_crankshaft()); CHECK_EQ(i + 1, CountNativeContexts()); @@ -1476,7 +1479,7 @@ TEST(TestInternalWeakListsTraverseWithGC) { CHECK_EQ(i + 1, CountNativeContextsWithGC(isolate, i / 2 + 1)); } - bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); + bool opt = (FLAG_always_opt && isolate->use_crankshaft()); // Compile a number of functions the length of the weak list of optimized // functions both with and without GCs while iterating the list. @@ -1720,12 +1723,12 @@ TEST(LeakNativeContextViaMap) { ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); ctx2->Exit(); v8::Local<v8::Context>::New(isolate, ctx1)->Exit(); - ctx1p.Dispose(isolate); + ctx1p.Dispose(); v8::V8::ContextDisposedNotification(); } HEAP->CollectAllAvailableGarbage(); CHECK_EQ(2, NumberOfGlobalObjects()); - ctx2p.Dispose(isolate); + ctx2p.Dispose(); HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } @@ -1766,12 +1769,12 @@ TEST(LeakNativeContextViaFunction) { ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); ctx2->Exit(); ctx1->Exit(); - ctx1p.Dispose(ctx1->GetIsolate()); + ctx1p.Dispose(); v8::V8::ContextDisposedNotification(); } HEAP->CollectAllAvailableGarbage(); CHECK_EQ(2, NumberOfGlobalObjects()); - ctx2p.Dispose(isolate); + ctx2p.Dispose(); HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } @@ -1810,12 +1813,12 @@ TEST(LeakNativeContextViaMapKeyed) { ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); ctx2->Exit(); ctx1->Exit(); - ctx1p.Dispose(ctx1->GetIsolate()); + ctx1p.Dispose(); v8::V8::ContextDisposedNotification(); } HEAP->CollectAllAvailableGarbage(); CHECK_EQ(2, NumberOfGlobalObjects()); - ctx2p.Dispose(isolate); + ctx2p.Dispose(); HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } @@ -1858,12 +1861,12 @@ TEST(LeakNativeContextViaMapProto) { ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); ctx2->Exit(); ctx1->Exit(); - ctx1p.Dispose(isolate); + ctx1p.Dispose(); v8::V8::ContextDisposedNotification(); } HEAP->CollectAllAvailableGarbage(); CHECK_EQ(2, NumberOfGlobalObjects()); - ctx2p.Dispose(isolate); + ctx2p.Dispose(); HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } @@ -1876,7 +1879,7 @@ TEST(InstanceOfStubWriteBarrier) { #endif CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft()) return; + if (!i::Isolate::Current()->use_crankshaft()) return; if (i::FLAG_force_marking_deque_overflows) return; v8::HandleScope outer_scope(v8::Isolate::GetCurrent()); @@ -1993,7 +1996,7 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) { #endif CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft()) return; + if (!i::Isolate::Current()->use_crankshaft()) return; v8::HandleScope outer_scope(v8::Isolate::GetCurrent()); { @@ -2050,7 +2053,7 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) { #endif CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft()) return; + if (!i::Isolate::Current()->use_crankshaft()) return; v8::HandleScope outer_scope(CcTest::isolate()); { @@ -2089,7 +2092,7 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) { TEST(OptimizedAllocationAlwaysInNewSpace) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); @@ -2118,7 +2121,7 @@ TEST(OptimizedAllocationAlwaysInNewSpace) { TEST(OptimizedPretenuringAllocationFolding) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2154,7 +2157,7 @@ TEST(OptimizedPretenuringAllocationFolding) { TEST(OptimizedPretenuringAllocationFoldingBlocks) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2190,7 +2193,7 @@ TEST(OptimizedPretenuringAllocationFoldingBlocks) { TEST(OptimizedPretenuringObjectArrayLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2215,7 +2218,7 @@ TEST(OptimizedPretenuringObjectArrayLiterals) { TEST(OptimizedPretenuringMixedInObjectProperties) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2246,7 +2249,7 @@ TEST(OptimizedPretenuringMixedInObjectProperties) { TEST(OptimizedPretenuringDoubleArrayProperties) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2271,7 +2274,7 @@ TEST(OptimizedPretenuringDoubleArrayProperties) { TEST(OptimizedPretenuringdoubleArrayLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2296,7 +2299,7 @@ TEST(OptimizedPretenuringdoubleArrayLiterals) { TEST(OptimizedPretenuringNestedMixedArrayLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2330,7 +2333,7 @@ TEST(OptimizedPretenuringNestedMixedArrayLiterals) { TEST(OptimizedPretenuringNestedObjectLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2364,7 +2367,7 @@ TEST(OptimizedPretenuringNestedObjectLiterals) { TEST(OptimizedPretenuringNestedDoubleLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2401,7 +2404,7 @@ TEST(OptimizedPretenuringNestedDoubleLiterals) { TEST(OptimizedAllocationArrayLiterals) { i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); @@ -2428,7 +2431,7 @@ TEST(OptimizedPretenuringCallNew) { i::FLAG_allow_natives_syntax = true; i::FLAG_pretenuring_call_new = true; CcTest::InitializeVM(); - if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return; + if (!i::Isolate::Current()->use_crankshaft() || i::FLAG_always_opt) return; if (i::FLAG_gc_global || i::FLAG_stress_compaction) return; v8::HandleScope scope(CcTest::isolate()); HEAP->SetNewSpaceHighPromotionModeActive(true); @@ -2691,9 +2694,7 @@ TEST(Regress2211) { // In the first iteration, set hidden value first and identity hash second. // In the second iteration, reverse the order. if (i == 0) obj->SetHiddenValue(v8_str("key string"), value); - MaybeObject* maybe_obj = internal_obj->SetIdentityHash(hash, - ALLOW_CREATION); - CHECK(!maybe_obj->IsFailure()); + JSObject::SetIdentityHash(internal_obj, hash); if (i == 1) obj->SetHiddenValue(v8_str("key string"), value); // Check values. @@ -2898,7 +2899,7 @@ void ReleaseStackTraceDataTest(const char* source, const char* accessor) { // to check whether the data is being released since the external string // resource's callback is fired when the external string is GC'ed. FLAG_use_ic = false; // ICs retain objects. - FLAG_parallel_recompilation = false; + FLAG_concurrent_recompilation = false; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); SourceResource* resource = new SourceResource(i::StrDup(source)); @@ -3140,16 +3141,6 @@ TEST(Regress169209) { i::FLAG_allow_natives_syntax = true; i::FLAG_flush_code_incrementally = true; - // Experimental natives are compiled during snapshot deserialization. - // This test breaks because heap layout changes in a way that closure - // is visited before shared function info. - i::FLAG_harmony_typed_arrays = false; - i::FLAG_harmony_array_buffer = false; - - // Disable loading the i18n extension which breaks the assumptions of this - // test about the heap layout. - i::FLAG_enable_i18n = false; - CcTest::InitializeVM(); Isolate* isolate = Isolate::Current(); Heap* heap = isolate->heap(); @@ -3427,7 +3418,7 @@ TEST(DeferredHandles) { CcTest::InitializeVM(); Isolate* isolate = Isolate::Current(); Heap* heap = isolate->heap(); - v8::HandleScope scope; + v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate)); v8::ImplementationUtilities::HandleScopeData* data = isolate->handle_scope_data(); Handle<Object> init(heap->empty_string(), isolate); diff --git a/deps/v8/test/cctest/test-lockers.cc b/deps/v8/test/cctest/test-lockers.cc index a8e870e671..a143d583fd 100644 --- a/deps/v8/test/cctest/test-lockers.cc +++ b/deps/v8/test/cctest/test-lockers.cc @@ -41,7 +41,6 @@ #include "parser.h" #include "unicode-inl.h" -using ::v8::AccessorInfo; using ::v8::Context; using ::v8::Extension; using ::v8::Function; @@ -130,20 +129,18 @@ class JoinableThread { public: explicit JoinableThread(const char* name) : name_(name), - semaphore_(i::OS::CreateSemaphore(0)), + semaphore_(0), thread_(this) { } - virtual ~JoinableThread() { - delete semaphore_; - } + virtual ~JoinableThread() {} void Start() { thread_.Start(); } void Join() { - semaphore_->Wait(); + semaphore_.Wait(); } virtual void Run() = 0; @@ -158,7 +155,7 @@ class JoinableThread { virtual void Run() { joinable_thread_->Run(); - joinable_thread_->semaphore_->Signal(); + joinable_thread_->semaphore_.Signal(); } private: @@ -166,7 +163,7 @@ class JoinableThread { }; const char* name_; - i::Semaphore* semaphore_; + i::Semaphore semaphore_; ThreadWithSemaphore thread_; friend class ThreadWithSemaphore; diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 8bcb5f7d29..f752c36ccb 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/deps/v8/test/cctest/test-log.cc @@ -27,7 +27,6 @@ // // Tests of logging functions from log.h -#define V8_DISABLE_DEPRECATIONS 1 #ifdef __linux__ #include <pthread.h> #include <signal.h> @@ -44,7 +43,6 @@ #include "v8utils.h" #include "cctest.h" #include "vm-state-inl.h" -#undef V8_DISABLE_DEPRECATIONS using v8::internal::Address; using v8::internal::EmbeddedVector; @@ -56,13 +54,12 @@ namespace { class ScopedLoggerInitializer { public: - explicit ScopedLoggerInitializer(bool prof_lazy) + ScopedLoggerInitializer() : saved_log_(i::FLAG_log), - saved_prof_lazy_(i::FLAG_prof_lazy), saved_prof_(i::FLAG_prof), temp_file_(NULL), // Need to run this prior to creating the scope. - trick_to_run_init_flags_(init_flags_(prof_lazy)), + trick_to_run_init_flags_(init_flags_()), scope_(v8::Isolate::GetCurrent()), env_(v8::Context::New(v8::Isolate::GetCurrent())), logger_(i::Isolate::Current()->logger()) { @@ -73,7 +70,6 @@ class ScopedLoggerInitializer { env_->Exit(); logger_->TearDown(); if (temp_file_ != NULL) fclose(temp_file_); - i::FLAG_prof_lazy = saved_prof_lazy_; i::FLAG_prof = saved_prof_; i::FLAG_log = saved_log_; } @@ -91,16 +87,14 @@ class ScopedLoggerInitializer { } private: - static bool init_flags_(bool prof_lazy) { + static bool init_flags_() { i::FLAG_log = true; i::FLAG_prof = true; - i::FLAG_prof_lazy = prof_lazy; i::FLAG_logfile = i::Log::kLogToTemporaryFile; - return prof_lazy; + return false; } const bool saved_log_; - const bool saved_prof_lazy_; const bool saved_prof_; FILE* temp_file_; const bool trick_to_run_init_flags_; @@ -124,70 +118,6 @@ static const char* StrNStr(const char* s1, const char* s2, int n) { } -TEST(ProfLazyMode) { - ScopedLoggerInitializer initialize_logger(true); - Logger* logger = initialize_logger.logger(); - - if (!i::V8::UseCrankshaft()) return; - - logger->StringEvent("test-start", ""); - CompileRun("var a = (function(x) { return x + 1; })(10);"); - logger->StringEvent("test-profiler-start", ""); - v8::V8::ResumeProfiler(); - CompileRun( - "var b = (function(x) { return x + 2; })(10);\n" - "var c = (function(x) { return x + 3; })(10);\n" - "var d = (function(x) { return x + 4; })(10);\n" - "var e = (function(x) { return x + 5; })(10);"); - v8::V8::PauseProfiler(); - logger->StringEvent("test-profiler-stop", ""); - CompileRun("var f = (function(x) { return x + 6; })(10);"); - // Check that profiling can be resumed again. - logger->StringEvent("test-profiler-start-2", ""); - v8::V8::ResumeProfiler(); - CompileRun( - "var g = (function(x) { return x + 7; })(10);\n" - "var h = (function(x) { return x + 8; })(10);\n" - "var i = (function(x) { return x + 9; })(10);\n" - "var j = (function(x) { return x + 10; })(10);"); - v8::V8::PauseProfiler(); - logger->StringEvent("test-profiler-stop-2", ""); - logger->StringEvent("test-stop", ""); - - bool exists = false; - i::Vector<const char> log( - i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); - CHECK(exists); - - const char* test_start_position = - StrNStr(log.start(), "test-start,", log.length()); - CHECK_NE(NULL, test_start_position); - const char* test_profiler_start_position = - StrNStr(log.start(), "test-profiler-start,", log.length()); - CHECK_NE(NULL, test_profiler_start_position); - CHECK_GT(test_profiler_start_position, test_start_position); - const char* test_profiler_stop_position = - StrNStr(log.start(), "test-profiler-stop,", log.length()); - CHECK_NE(NULL, test_profiler_stop_position); - CHECK_GT(test_profiler_stop_position, test_profiler_start_position); - const char* test_profiler_start_2_position = - StrNStr(log.start(), "test-profiler-start-2,", log.length()); - CHECK_NE(NULL, test_profiler_start_2_position); - CHECK_GT(test_profiler_start_2_position, test_profiler_stop_position); - - // Nothing must be logged until profiling is resumed. - CHECK_EQ(NULL, StrNStr(test_start_position, - "code-creation,", - static_cast<int>(test_profiler_start_position - - test_start_position))); - // Nothing must be logged while profiling is suspended. - CHECK_EQ(NULL, StrNStr(test_profiler_stop_position, - "code-creation,", - static_cast<int>(test_profiler_start_2_position - - test_profiler_stop_position))); -} - - // BUG(913). Need to implement support for profiling multiple VM threads. #if 0 @@ -197,7 +127,7 @@ class LoopingThread : public v8::internal::Thread { public: explicit LoopingThread(v8::internal::Isolate* isolate) : v8::internal::Thread(isolate), - semaphore_(v8::internal::OS::CreateSemaphore(0)), + semaphore_(new v8::internal::Semaphore(0)), run_(true) { } @@ -283,7 +213,7 @@ class TestSampler : public v8::internal::Sampler { public: explicit TestSampler(v8::internal::Isolate* isolate) : Sampler(isolate, 0, true, true), - semaphore_(v8::internal::OS::CreateSemaphore(0)), + semaphore_(new v8::internal::Semaphore(0)), was_sample_stack_called_(false) { } @@ -396,7 +326,7 @@ static void ObjMethod1(const v8::FunctionCallbackInfo<v8::Value>& args) { TEST(LogCallbacks) { - ScopedLoggerInitializer initialize_logger(false); + ScopedLoggerInitializer initialize_logger; Logger* logger = initialize_logger.logger(); v8::Local<v8::FunctionTemplate> obj = @@ -445,7 +375,7 @@ static void Prop2Getter(v8::Local<v8::String> property, TEST(LogAccessorCallbacks) { - ScopedLoggerInitializer initialize_logger(false); + ScopedLoggerInitializer initialize_logger; Logger* logger = initialize_logger.logger(); v8::Local<v8::FunctionTemplate> obj = @@ -486,18 +416,6 @@ TEST(LogAccessorCallbacks) { } -TEST(IsLoggingPreserved) { - ScopedLoggerInitializer initialize_logger(false); - Logger* logger = initialize_logger.logger(); - - CHECK(logger->is_logging()); - logger->ResumeProfiler(); - CHECK(logger->is_logging()); - logger->PauseProfiler(); - CHECK(logger->is_logging()); -} - - typedef i::NativesCollection<i::TEST> TestSources; @@ -509,12 +427,9 @@ TEST(EquivalenceOfLoggingAndTraversal) { // it launches a new cctest instance for every test. To be sure that launching // cctest manually also works, please be sure that no tests below // are using V8. - // - // P.S. No, V8 can't be re-initialized after disposal, see include/v8.h. - CHECK(!i::V8::IsRunning()); // Start with profiling to capture all code events from the beginning. - ScopedLoggerInitializer initialize_logger(false); + ScopedLoggerInitializer initialize_logger; Logger* logger = initialize_logger.logger(); // Compile and run a function that creates other functions. @@ -523,7 +438,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { " obj.test =\n" " (function a(j) { return function b() { return j; } })(100);\n" "})(this);"); - v8::V8::PauseProfiler(); + logger->StopProfiler(); HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); logger->StringEvent("test-logging-done", ""); diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc index 0d8c00d2e1..33d9230e01 100644 --- a/deps/v8/test/cctest/test-mark-compact.cc +++ b/deps/v8/test/cctest/test-mark-compact.cc @@ -147,86 +147,88 @@ TEST(NoPromotion) { TEST(MarkCompactCollector) { + FLAG_incremental_marking = false; CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Heap* heap = isolate->heap(); v8::HandleScope sc(CcTest::isolate()); + // call mark-compact when heap is empty - HEAP->CollectGarbage(OLD_POINTER_SPACE); + heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 1"); // 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, "trigger 2"); - 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, "trigger 3"); + mapp = heap->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)->ToObjectChecked(); // allocate a garbage String* func_name = String::cast( - HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked()); + heap->InternalizeUtf8String("theFunction")->ToObjectChecked()); SharedFunctionInfo* function_share = SharedFunctionInfo::cast( - HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked()); + heap->AllocateSharedFunctionInfo(func_name)->ToObjectChecked()); JSFunction* function = JSFunction::cast( - HEAP->AllocateFunction(*Isolate::Current()->function_map(), + heap->AllocateFunction(*isolate->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); - Isolate::Current()->context()->global_object()->SetProperty( + isolate->context()->global_object()->SetProperty( func_name, function, NONE, kNonStrictMode)->ToObjectChecked(); JSObject* obj = JSObject::cast( - HEAP->AllocateJSObject(function)->ToObjectChecked()); - HEAP->CollectGarbage(OLD_POINTER_SPACE); + heap->AllocateJSObject(function)->ToObjectChecked()); + heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 4"); func_name = String::cast( - HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked()); - CHECK(Isolate::Current()->context()->global_object()-> - HasLocalProperty(func_name)); - Object* func_value = Isolate::Current()->context()->global_object()-> + heap->InternalizeUtf8String("theFunction")->ToObjectChecked()); + CHECK(isolate->context()->global_object()->HasLocalProperty(func_name)); + Object* func_value = isolate->context()->global_object()-> 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->InternalizeUtf8String("theObject")->ToObjectChecked()); - Isolate::Current()->context()->global_object()->SetProperty( + String::cast(heap->InternalizeUtf8String("theObject")->ToObjectChecked()); + isolate->context()->global_object()->SetProperty( obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked(); String* prop_name = - String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked()); + String::cast(heap->InternalizeUtf8String("theSlot")->ToObjectChecked()); obj->SetProperty(prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); - HEAP->CollectGarbage(OLD_POINTER_SPACE); + heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 5"); obj_name = - String::cast(HEAP->InternalizeUtf8String("theObject")->ToObjectChecked()); - CHECK(Isolate::Current()->context()->global_object()-> - HasLocalProperty(obj_name)); - CHECK(Isolate::Current()->context()->global_object()-> + String::cast(heap->InternalizeUtf8String("theObject")->ToObjectChecked()); + CHECK(isolate->context()->global_object()->HasLocalProperty(obj_name)); + CHECK(isolate->context()->global_object()-> GetProperty(obj_name)->ToObjectChecked()->IsJSObject()); - obj = JSObject::cast(Isolate::Current()->context()->global_object()-> + obj = JSObject::cast(isolate->context()->global_object()-> GetProperty(obj_name)->ToObjectChecked()); prop_name = - String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked()); + String::cast(heap->InternalizeUtf8String("theSlot")->ToObjectChecked()); CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23)); } @@ -305,7 +307,7 @@ static void WeakPointerCallback(v8::Isolate* isolate, void* id) { ASSERT(id == reinterpret_cast<void*>(1234)); NumberOfWeakCalls++; - handle->Dispose(isolate); + handle->Dispose(); } @@ -541,7 +543,7 @@ TEST(BootUpMemoryUse) { intptr_t initial_memory = MemoryInUse(); // Avoid flakiness. FLAG_crankshaft = false; - FLAG_parallel_recompilation = false; + FLAG_concurrent_recompilation = false; // Only Linux has the proc filesystem and only if it is mapped. If it's not // there we just skip the test. @@ -570,7 +572,7 @@ intptr_t ShortLivingIsolate() { v8::Isolate* isolate = v8::Isolate::New(); { v8::Isolate::Scope isolate_scope(isolate); v8::Locker lock(isolate); - v8::HandleScope handle_scope; + v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); CHECK(!context.IsEmpty()); } diff --git a/deps/v8/test/cctest/test-mutex.cc b/deps/v8/test/cctest/test-mutex.cc new file mode 100644 index 0000000000..cdc829f156 --- /dev/null +++ b/deps/v8/test/cctest/test-mutex.cc @@ -0,0 +1,118 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <cstdlib> + +#include "v8.h" + +#include "cctest.h" +#include "platform/mutex.h" + +using namespace ::v8::internal; + + +TEST(LockGuardMutex) { + Mutex mutex; + { LockGuard<Mutex> lock_guard(&mutex); + } + { LockGuard<Mutex> lock_guard(&mutex); + } +} + + +TEST(LockGuardRecursiveMutex) { + RecursiveMutex recursive_mutex; + { LockGuard<RecursiveMutex> lock_guard(&recursive_mutex); + } + { LockGuard<RecursiveMutex> lock_guard1(&recursive_mutex); + LockGuard<RecursiveMutex> lock_guard2(&recursive_mutex); + } +} + + +TEST(LockGuardLazyMutex) { + LazyMutex lazy_mutex = LAZY_MUTEX_INITIALIZER; + { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); + } + { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); + } +} + + +TEST(LockGuardLazyRecursiveMutex) { + LazyRecursiveMutex lazy_recursive_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER; + { LockGuard<RecursiveMutex> lock_guard(lazy_recursive_mutex.Pointer()); + } + { LockGuard<RecursiveMutex> lock_guard1(lazy_recursive_mutex.Pointer()); + LockGuard<RecursiveMutex> lock_guard2(lazy_recursive_mutex.Pointer()); + } +} + + +TEST(MultipleMutexes) { + Mutex mutex1; + Mutex mutex2; + Mutex mutex3; + // Order 1 + mutex1.Lock(); + mutex2.Lock(); + mutex3.Lock(); + mutex1.Unlock(); + mutex2.Unlock(); + mutex3.Unlock(); + // Order 2 + mutex1.Lock(); + mutex2.Lock(); + mutex3.Lock(); + mutex3.Unlock(); + mutex2.Unlock(); + mutex1.Unlock(); +} + + +TEST(MultipleRecursiveMutexes) { + RecursiveMutex recursive_mutex1; + RecursiveMutex recursive_mutex2; + // Order 1 + recursive_mutex1.Lock(); + recursive_mutex2.Lock(); + CHECK(recursive_mutex1.TryLock()); + CHECK(recursive_mutex2.TryLock()); + recursive_mutex1.Unlock(); + recursive_mutex1.Unlock(); + recursive_mutex2.Unlock(); + recursive_mutex2.Unlock(); + // Order 2 + recursive_mutex1.Lock(); + CHECK(recursive_mutex1.TryLock()); + recursive_mutex2.Lock(); + CHECK(recursive_mutex2.TryLock()); + recursive_mutex2.Unlock(); + recursive_mutex1.Unlock(); + recursive_mutex2.Unlock(); + recursive_mutex1.Unlock(); +} diff --git a/deps/v8/test/cctest/test-object-observe.cc b/deps/v8/test/cctest/test-object-observe.cc index 44ddb6fa20..b129ff3af4 100644 --- a/deps/v8/test/cctest/test-object-observe.cc +++ b/deps/v8/test/cctest/test-object-observe.cc @@ -313,11 +313,13 @@ static void ExpectRecords(Handle<Value> records, recordObj->Get(String::New("object")))); CHECK(String::New(expectations[i].type)->Equals( recordObj->Get(String::New("type")))); - CHECK(String::New(expectations[i].name)->Equals( - recordObj->Get(String::New("name")))); - if (!expectations[i].old_value.IsEmpty()) { - CHECK(expectations[i].old_value->Equals( - recordObj->Get(String::New("oldValue")))); + if (strcmp("splice", expectations[i].type) != 0) { + CHECK(String::New(expectations[i].name)->Equals( + recordObj->Get(String::New("name")))); + if (!expectations[i].old_value.IsEmpty()) { + CHECK(expectations[i].old_value->Equals( + recordObj->Get(String::New("oldValue")))); + } } } } @@ -435,14 +437,281 @@ TEST(ObservationWeakMap) { i::Handle<i::JSWeakMap> objectInfoMap = i::Handle<i::JSWeakMap>::cast( i::GetProperty(observation_state, "objectInfoMap")); - i::Handle<i::JSWeakMap> notifierTargetMap = + i::Handle<i::JSWeakMap> notifierObjectInfoMap = i::Handle<i::JSWeakMap>::cast( - i::GetProperty(observation_state, "notifierTargetMap")); + i::GetProperty(observation_state, "notifierObjectInfoMap")); CHECK_EQ(1, NumberOfElements(callbackInfoMap)); CHECK_EQ(1, NumberOfElements(objectInfoMap)); - CHECK_EQ(1, NumberOfElements(notifierTargetMap)); + CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap)); HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); CHECK_EQ(0, NumberOfElements(callbackInfoMap)); CHECK_EQ(0, NumberOfElements(objectInfoMap)); - CHECK_EQ(0, NumberOfElements(notifierTargetMap)); + CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap)); +} + + +static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType, + Local<Value>) { + return true; +} + + +static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType, + Local<Value>) { + return true; +} + + +static AccessType g_access_block_type = ACCESS_GET; + + +static bool NamedAccessAllowUnlessBlocked(Local<Object> host, + Local<Value> key, + AccessType type, + Local<Value>) { + if (type != g_access_block_type) return true; + Handle<Object> global = Context::GetCurrent()->Global(); + Handle<Value> blacklist = global->Get(String::New("blacklist")); + if (!blacklist->IsObject()) return true; + if (key->IsString()) return !blacklist.As<Object>()->Has(key); + return true; +} + + +static bool IndexedAccessAllowUnlessBlocked(Local<Object> host, + uint32_t index, + AccessType type, + Local<Value>) { + if (type != ACCESS_GET) return true; + Handle<Object> global = Context::GetCurrent()->Global(); + Handle<Value> blacklist = global->Get(String::New("blacklist")); + if (!blacklist->IsObject()) return true; + return !blacklist.As<Object>()->Has(index); +} + + +static bool BlockAccessKeys(Local<Object> host, Local<Value> key, + AccessType type, Local<Value>) { + Handle<Object> global = Context::GetCurrent()->Global(); + Handle<Value> blacklist = global->Get(String::New("blacklist")); + if (!blacklist->IsObject()) return true; + return type != ACCESS_KEYS || + !blacklist.As<Object>()->Has(String::New("__block_access_keys")); +} + + +static Handle<Object> CreateAccessCheckedObject( + NamedSecurityCallback namedCallback, + IndexedSecurityCallback indexedCallback) { + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(); + tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback); + Handle<Object> instance = tmpl->NewInstance(); + instance->CreationContext()->Global()->Set(String::New("obj"), instance); + return instance; +} + + +TEST(NamedAccessCheck) { + HarmonyIsolate isolate; + const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; + for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { + HandleScope scope(isolate.GetIsolate()); + LocalContext context; + g_access_block_type = types[i]; + Handle<Object> instance = CreateAccessCheckedObject( + NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed); + CompileRun("var records = null;" + "var objNoCheck = {};" + "var blacklist = {foo: true};" + "var observer = function(r) { records = r };" + "Object.observe(obj, observer);" + "Object.observe(objNoCheck, observer);"); + Handle<Value> obj_no_check = CompileRun("objNoCheck"); + { + LocalContext context2; + context2->Global()->Set(String::New("obj"), instance); + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); + CompileRun("var records2 = null;" + "var observer2 = function(r) { records2 = r };" + "Object.observe(obj, observer2);" + "Object.observe(objNoCheck, observer2);" + "obj.foo = 'bar';" + "Object.defineProperty(obj, 'foo', {value: 5});" + "Object.defineProperty(obj, 'foo', {get: function(){}});" + "obj.bar = 'baz';" + "objNoCheck.baz = 'quux'"); + const RecordExpectation expected_records2[] = { + { instance, "new", "foo", Handle<Value>() }, + { instance, "updated", "foo", String::New("bar") }, + { instance, "reconfigured", "foo", Number::New(5) }, + { instance, "new", "bar", Handle<Value>() }, + { obj_no_check, "new", "baz", Handle<Value>() }, + }; + EXPECT_RECORDS(CompileRun("records2"), expected_records2); + } + const RecordExpectation expected_records[] = { + { instance, "new", "bar", Handle<Value>() }, + { obj_no_check, "new", "baz", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records"), expected_records); + } +} + + +TEST(IndexedAccessCheck) { + HarmonyIsolate isolate; + const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; + for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { + HandleScope scope(isolate.GetIsolate()); + LocalContext context; + g_access_block_type = types[i]; + Handle<Object> instance = CreateAccessCheckedObject( + NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); + CompileRun("var records = null;" + "var objNoCheck = {};" + "var blacklist = {7: true};" + "var observer = function(r) { records = r };" + "Object.observe(obj, observer);" + "Object.observe(objNoCheck, observer);"); + Handle<Value> obj_no_check = CompileRun("objNoCheck"); + { + LocalContext context2; + context2->Global()->Set(String::New("obj"), instance); + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); + CompileRun("var records2 = null;" + "var observer2 = function(r) { records2 = r };" + "Object.observe(obj, observer2);" + "Object.observe(objNoCheck, observer2);" + "obj[7] = 'foo';" + "Object.defineProperty(obj, '7', {value: 5});" + "Object.defineProperty(obj, '7', {get: function(){}});" + "obj[8] = 'bar';" + "objNoCheck[42] = 'quux'"); + const RecordExpectation expected_records2[] = { + { instance, "new", "7", Handle<Value>() }, + { instance, "updated", "7", String::New("foo") }, + { instance, "reconfigured", "7", Number::New(5) }, + { instance, "new", "8", Handle<Value>() }, + { obj_no_check, "new", "42", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records2"), expected_records2); + } + const RecordExpectation expected_records[] = { + { instance, "new", "8", Handle<Value>() }, + { obj_no_check, "new", "42", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records"), expected_records); + } +} + + +TEST(SpliceAccessCheck) { + HarmonyIsolate isolate; + HandleScope scope(isolate.GetIsolate()); + LocalContext context; + g_access_block_type = ACCESS_GET; + Handle<Object> instance = CreateAccessCheckedObject( + NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); + CompileRun("var records = null;" + "obj[1] = 'foo';" + "obj.length = 2;" + "var objNoCheck = {1: 'bar', length: 2};" + "var blacklist = {1: true};" + "observer = function(r) { records = r };" + "Array.observe(obj, observer);" + "Array.observe(objNoCheck, observer);"); + Handle<Value> obj_no_check = CompileRun("objNoCheck"); + { + LocalContext context2; + context2->Global()->Set(String::New("obj"), instance); + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); + CompileRun("var records2 = null;" + "var observer2 = function(r) { records2 = r };" + "Array.observe(obj, observer2);" + "Array.observe(objNoCheck, observer2);" + // No one should hear about this: no splice records are emitted + // for access-checked objects + "[].push.call(obj, 5);" + "[].splice.call(obj, 1, 1);" + "[].pop.call(obj);" + "[].pop.call(objNoCheck);"); + // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things + // about splice records. For this test it's not so important since + // we just want to guarantee the machinery is in operation at all. + const RecordExpectation expected_records2[] = { + { obj_no_check, "splice", "", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records2"), expected_records2); + } + const RecordExpectation expected_records[] = { + { obj_no_check, "splice", "", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records"), expected_records); +} + + +TEST(DisallowAllForAccessKeys) { + HarmonyIsolate isolate; + HandleScope scope(isolate.GetIsolate()); + LocalContext context; + Handle<Object> instance = CreateAccessCheckedObject( + BlockAccessKeys, IndexedAccessAlwaysAllowed); + CompileRun("var records = null;" + "var objNoCheck = {};" + "var observer = function(r) { records = r };" + "var blacklist = {__block_access_keys: true};" + "Object.observe(obj, observer);" + "Object.observe(objNoCheck, observer);"); + Handle<Value> obj_no_check = CompileRun("objNoCheck"); + { + LocalContext context2; + context2->Global()->Set(String::New("obj"), instance); + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); + CompileRun("var records2 = null;" + "var observer2 = function(r) { records2 = r };" + "Object.observe(obj, observer2);" + "Object.observe(objNoCheck, observer2);" + "obj.foo = 'bar';" + "obj[5] = 'baz';" + "objNoCheck.baz = 'quux'"); + const RecordExpectation expected_records2[] = { + { instance, "new", "foo", Handle<Value>() }, + { instance, "new", "5", Handle<Value>() }, + { obj_no_check, "new", "baz", Handle<Value>() }, + }; + EXPECT_RECORDS(CompileRun("records2"), expected_records2); + } + const RecordExpectation expected_records[] = { + { obj_no_check, "new", "baz", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records"), expected_records); +} + + +TEST(AccessCheckDisallowApiModifications) { + HarmonyIsolate isolate; + HandleScope scope(isolate.GetIsolate()); + LocalContext context; + Handle<Object> instance = CreateAccessCheckedObject( + BlockAccessKeys, IndexedAccessAlwaysAllowed); + CompileRun("var records = null;" + "var observer = function(r) { records = r };" + "var blacklist = {__block_access_keys: true};" + "Object.observe(obj, observer);"); + { + LocalContext context2; + context2->Global()->Set(String::New("obj"), instance); + CompileRun("var records2 = null;" + "var observer2 = function(r) { records2 = r };" + "Object.observe(obj, observer2);"); + instance->Set(5, String::New("bar")); + instance->Set(String::New("foo"), String::New("bar")); + CompileRun(""); // trigger delivery + const RecordExpectation expected_records2[] = { + { instance, "new", "5", Handle<Value>() }, + { instance, "new", "foo", Handle<Value>() } + }; + EXPECT_RECORDS(CompileRun("records2"), expected_records2); + } + CHECK(CompileRun("records")->IsNull()); } diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index 999fe4c5bd..80b276c8f9 100644 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -313,9 +313,10 @@ TEST(StandAlonePreParserNoNatives) { TEST(RegressChromium62639) { v8::V8::Initialize(); + i::Isolate* isolate = i::Isolate::Current(); int marker; - i::Isolate::Current()->stack_guard()->SetStackLimit( + isolate->stack_guard()->SetStackLimit( reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); const char* program = "var x = 'something';\n" @@ -328,7 +329,7 @@ TEST(RegressChromium62639) { i::Utf8ToUtf16CharacterStream stream( reinterpret_cast<const i::byte*>(program), static_cast<unsigned>(strlen(program))); - i::ScriptDataImpl* data = i::PreParserApi::PreParse(&stream); + i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); CHECK(data->HasError()); delete data; } @@ -355,7 +356,7 @@ TEST(Regress928) { i::Handle<i::String> source( factory->NewStringFromAscii(i::CStrVector(program))); i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); - i::ScriptDataImpl* data = i::PreParserApi::PreParse(&stream); + i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); CHECK(!data->HasError()); data->Initialize(); @@ -1066,8 +1067,8 @@ i::Handle<i::String> FormatMessage(i::ScriptDataImpl* data) { i::GetProperty(builtins, "FormatMessage"); i::Handle<i::Object> arg_handles[] = { format, args_array }; bool has_exception = false; - i::Handle<i::Object> result = - i::Execution::Call(format_fun, builtins, 2, arg_handles, &has_exception); + i::Handle<i::Object> result = i::Execution::Call( + isolate, format_fun, builtins, 2, arg_handles, &has_exception); CHECK(!has_exception); CHECK(result->IsString()); for (int i = 0; i < args.length(); i++) { @@ -1263,10 +1264,6 @@ TEST(ParserSync) { NULL }; - // TODO(mstarzinger): Disabled in GC stress mode for now, we should find the - // correct timeout for this and re-enable this test again. - if (i::FLAG_stress_compaction) return; - i::Isolate* isolate = i::Isolate::Current(); i::Factory* factory = isolate->factory(); diff --git a/deps/v8/test/cctest/test-platform-linux.cc b/deps/v8/test/cctest/test-platform-linux.cc index 6bb2902f41..f289e94828 100644 --- a/deps/v8/test/cctest/test-platform-linux.cc +++ b/deps/v8/test/cctest/test-platform-linux.cc @@ -39,60 +39,7 @@ using namespace ::v8::internal; -static void yield() { - usleep(1); -} - -static const int kLockCounterLimit = 50; -static int busy_lock_counter = 0; - - -static void LoopIncrement(Mutex* mutex, int rem) { - while (true) { - int count = 0; - int last_count = -1; - do { - CHECK_EQ(0, mutex->Lock()); - count = busy_lock_counter; - CHECK_EQ(0, mutex->Unlock()); - yield(); - } while (count % 2 == rem && count < kLockCounterLimit); - if (count >= kLockCounterLimit) break; - CHECK_EQ(0, mutex->Lock()); - CHECK_EQ(count, busy_lock_counter); - CHECK(last_count == -1 || count == last_count + 1); - busy_lock_counter++; - last_count = count; - CHECK_EQ(0, mutex->Unlock()); - yield(); - } -} - - -static void* RunTestBusyLock(void* arg) { - LoopIncrement(static_cast<Mutex*>(arg), 0); - return 0; -} - - -// Runs two threads that repeatedly acquire the lock and conditionally -// increment a variable. -TEST(BusyLock) { - pthread_t other; - Mutex* mutex = OS::CreateMutex(); - int thread_created = pthread_create(&other, - NULL, - &RunTestBusyLock, - mutex); - CHECK_EQ(0, thread_created); - LoopIncrement(mutex, 1); - pthread_join(other, NULL); - delete mutex; -} - - TEST(VirtualMemory) { - OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); @@ -107,6 +54,5 @@ TEST(VirtualMemory) { TEST(GetCurrentProcessId) { - OS::SetUp(); CHECK_EQ(static_cast<int>(getpid()), OS::GetCurrentProcessId()); } diff --git a/deps/v8/test/cctest/test-platform-nullos.cc b/deps/v8/test/cctest/test-platform-nullos.cc deleted file mode 100644 index 3afbd90aec..0000000000 --- a/deps/v8/test/cctest/test-platform-nullos.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2006-2008 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. -// -// Tests of the TokenLock class from lock.h - -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> // for usleep() - -#include "v8.h" - -#include "platform.h" -#include "cctest.h" - -using namespace ::v8::internal; - - -static void yield() { - UNIMPLEMENTED(); -} - -static const int kLockCounterLimit = 50; -static int busy_lock_counter = 0; - - -static void LoopIncrement(Mutex* mutex, int rem) { - while (true) { - int count = 0; - int last_count = -1; - do { - CHECK_EQ(0, mutex->Lock()); - count = busy_lock_counter; - CHECK_EQ(0, mutex->Unlock()); - yield(); - } while (count % 2 == rem && count < kLockCounterLimit); - if (count >= kLockCounterLimit) break; - CHECK_EQ(0, mutex->Lock()); - CHECK_EQ(count, busy_lock_counter); - CHECK(last_count == -1 || count == last_count + 1); - busy_lock_counter++; - last_count = count; - CHECK_EQ(0, mutex->Unlock()); - yield(); - } -} - - -static void* RunTestBusyLock(void* arg) { - LoopIncrement(static_cast<Mutex*>(arg), 0); - return 0; -} - - -// Runs two threads that repeatedly acquire the lock and conditionally -// increment a variable. -TEST(BusyLock) { - pthread_t other; - Mutex* mutex = OS::CreateMutex(); - int thread_created = pthread_create(&other, - NULL, - &RunTestBusyLock, - mutex); - CHECK_EQ(0, thread_created); - LoopIncrement(mutex, 1); - pthread_join(other, NULL); - delete mutex; -} - - -TEST(VirtualMemory) { - VirtualMemory* vm = new VirtualMemory(1 * MB); - CHECK(vm->IsReserved()); - void* block_addr = vm->address(); - size_t block_size = 4 * KB; - CHECK(vm->Commit(block_addr, block_size, false)); - // Check whether we can write to memory. - int* addr = static_cast<int*>(block_addr); - addr[KB-1] = 2; - CHECK(vm->Uncommit(block_addr, block_size)); - delete vm; -} diff --git a/deps/v8/test/cctest/test-platform-win32.cc b/deps/v8/test/cctest/test-platform-win32.cc index a5089d360a..d7fdab11ed 100644 --- a/deps/v8/test/cctest/test-platform-win32.cc +++ b/deps/v8/test/cctest/test-platform-win32.cc @@ -39,7 +39,6 @@ using namespace ::v8::internal; TEST(VirtualMemory) { - OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); @@ -54,7 +53,6 @@ TEST(VirtualMemory) { TEST(GetCurrentProcessId) { - OS::SetUp(); CHECK_EQ(static_cast<int>(::GetCurrentProcessId()), OS::GetCurrentProcessId()); } diff --git a/deps/v8/test/cctest/test-platform.cc b/deps/v8/test/cctest/test-platform.cc index 2d8eb201e8..079cbd121b 100644 --- a/deps/v8/test/cctest/test-platform.cc +++ b/deps/v8/test/cctest/test-platform.cc @@ -32,11 +32,6 @@ using namespace ::v8::internal; -TEST(NumberOfCores) { - CHECK_GT(OS::NumberOfCores(), 0); -} - - #ifdef __GNUC__ #define ASM __asm__ __volatile__ diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc index f56275c1be..7504b171de 100644 --- a/deps/v8/test/cctest/test-profile-generator.cc +++ b/deps/v8/test/cctest/test-profile-generator.cc @@ -132,14 +132,12 @@ TEST(ProfileTreeAddPathFromStart) { CHECK_EQ(NULL, helper.Walk(&entry3)); ProfileNode* node1 = helper.Walk(&entry1); CHECK_NE(NULL, node1); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(0, node1->self_ticks()); CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); ProfileNode* node2 = helper.Walk(&entry1, &entry2); CHECK_NE(NULL, node2); CHECK_NE(node1, node2); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(0, node2->self_ticks()); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2)); @@ -147,18 +145,14 @@ TEST(ProfileTreeAddPathFromStart) { CHECK_NE(NULL, node3); CHECK_NE(node1, node3); CHECK_NE(node2, node3); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(1, node3->self_ticks()); tree.AddPathFromStart(path_vec); CHECK_EQ(node1, helper.Walk(&entry1)); CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(0, node1->self_ticks()); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(0, node2->self_ticks()); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(2, node3->self_ticks()); CodeEntry* path2[] = {&entry1, &entry2, &entry2}; @@ -172,12 +166,10 @@ TEST(ProfileTreeAddPathFromStart) { CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(2, node3->self_ticks()); ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2); CHECK_NE(NULL, node4); CHECK_NE(node3, node4); - CHECK_EQ(0, node4->total_ticks()); CHECK_EQ(1, node4->self_ticks()); } @@ -199,14 +191,12 @@ TEST(ProfileTreeAddPathFromEnd) { CHECK_EQ(NULL, helper.Walk(&entry3)); ProfileNode* node1 = helper.Walk(&entry1); CHECK_NE(NULL, node1); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(0, node1->self_ticks()); CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); ProfileNode* node2 = helper.Walk(&entry1, &entry2); CHECK_NE(NULL, node2); CHECK_NE(node1, node2); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(0, node2->self_ticks()); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2)); @@ -214,18 +204,14 @@ TEST(ProfileTreeAddPathFromEnd) { CHECK_NE(NULL, node3); CHECK_NE(node1, node3); CHECK_NE(node2, node3); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(1, node3->self_ticks()); tree.AddPathFromEnd(path_vec); CHECK_EQ(node1, helper.Walk(&entry1)); CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(0, node1->self_ticks()); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(0, node2->self_ticks()); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(2, node3->self_ticks()); CodeEntry* path2[] = {&entry2, &entry2, &entry1}; @@ -239,28 +225,18 @@ TEST(ProfileTreeAddPathFromEnd) { CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(2, node3->self_ticks()); ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2); CHECK_NE(NULL, node4); CHECK_NE(node3, node4); - CHECK_EQ(0, node4->total_ticks()); CHECK_EQ(1, node4->self_ticks()); } TEST(ProfileTreeCalculateTotalTicks) { ProfileTree empty_tree; - CHECK_EQ(0, empty_tree.root()->total_ticks()); - CHECK_EQ(0, empty_tree.root()->self_ticks()); - empty_tree.CalculateTotalTicks(); - CHECK_EQ(0, empty_tree.root()->total_ticks()); CHECK_EQ(0, empty_tree.root()->self_ticks()); empty_tree.root()->IncrementSelfTicks(); - CHECK_EQ(0, empty_tree.root()->total_ticks()); - CHECK_EQ(1, empty_tree.root()->self_ticks()); - empty_tree.CalculateTotalTicks(); - CHECK_EQ(1, empty_tree.root()->total_ticks()); CHECK_EQ(1, empty_tree.root()->self_ticks()); CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); @@ -271,17 +247,11 @@ TEST(ProfileTreeCalculateTotalTicks) { ProfileTree single_child_tree; single_child_tree.AddPathFromStart(e1_path_vec); single_child_tree.root()->IncrementSelfTicks(); - CHECK_EQ(0, single_child_tree.root()->total_ticks()); CHECK_EQ(1, single_child_tree.root()->self_ticks()); ProfileTreeTestHelper single_child_helper(&single_child_tree); ProfileNode* node1 = single_child_helper.Walk(&entry1); CHECK_NE(NULL, node1); - CHECK_EQ(0, node1->total_ticks()); - CHECK_EQ(1, node1->self_ticks()); - single_child_tree.CalculateTotalTicks(); - CHECK_EQ(2, single_child_tree.root()->total_ticks()); CHECK_EQ(1, single_child_tree.root()->self_ticks()); - CHECK_EQ(1, node1->total_ticks()); CHECK_EQ(1, node1->self_ticks()); CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); @@ -297,24 +267,16 @@ TEST(ProfileTreeCalculateTotalTicks) { flat_tree.AddPathFromStart(e1_e2_path_vec); flat_tree.AddPathFromStart(e1_e2_path_vec); // Results in {root,0,0} -> {entry1,0,2} -> {entry2,0,3} - CHECK_EQ(0, flat_tree.root()->total_ticks()); CHECK_EQ(0, flat_tree.root()->self_ticks()); node1 = flat_helper.Walk(&entry1); CHECK_NE(NULL, node1); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(2, node1->self_ticks()); ProfileNode* node2 = flat_helper.Walk(&entry1, &entry2); CHECK_NE(NULL, node2); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(3, node2->self_ticks()); - flat_tree.CalculateTotalTicks(); // Must calculate {root,5,0} -> {entry1,5,2} -> {entry2,3,3} - CHECK_EQ(5, flat_tree.root()->total_ticks()); CHECK_EQ(0, flat_tree.root()->self_ticks()); - CHECK_EQ(5, node1->total_ticks()); CHECK_EQ(2, node1->self_ticks()); - CHECK_EQ(3, node2->total_ticks()); - CHECK_EQ(3, node2->self_ticks()); CodeEntry* e2_path[] = {&entry2}; Vector<CodeEntry*> e2_path_vec( @@ -339,37 +301,26 @@ TEST(ProfileTreeCalculateTotalTicks) { // Results in -> {entry1,0,2} -> {entry2,0,1} // {root,0,0} -> {entry2,0,3} // -> {entry3,0,4} - CHECK_EQ(0, wide_tree.root()->total_ticks()); CHECK_EQ(0, wide_tree.root()->self_ticks()); node1 = wide_helper.Walk(&entry1); CHECK_NE(NULL, node1); - CHECK_EQ(0, node1->total_ticks()); CHECK_EQ(2, node1->self_ticks()); ProfileNode* node1_2 = wide_helper.Walk(&entry1, &entry2); CHECK_NE(NULL, node1_2); - CHECK_EQ(0, node1_2->total_ticks()); CHECK_EQ(1, node1_2->self_ticks()); node2 = wide_helper.Walk(&entry2); CHECK_NE(NULL, node2); - CHECK_EQ(0, node2->total_ticks()); CHECK_EQ(3, node2->self_ticks()); ProfileNode* node3 = wide_helper.Walk(&entry3); CHECK_NE(NULL, node3); - CHECK_EQ(0, node3->total_ticks()); CHECK_EQ(4, node3->self_ticks()); - wide_tree.CalculateTotalTicks(); // Calculates -> {entry1,3,2} -> {entry2,1,1} // {root,10,0} -> {entry2,3,3} // -> {entry3,4,4} - CHECK_EQ(10, wide_tree.root()->total_ticks()); CHECK_EQ(0, wide_tree.root()->self_ticks()); - CHECK_EQ(3, node1->total_ticks()); CHECK_EQ(2, node1->self_ticks()); - CHECK_EQ(1, node1_2->total_ticks()); CHECK_EQ(1, node1_2->self_ticks()); - CHECK_EQ(3, node2->total_ticks()); CHECK_EQ(3, node2->self_ticks()); - CHECK_EQ(4, node3->total_ticks()); CHECK_EQ(4, node3->self_ticks()); } @@ -448,7 +399,7 @@ class TestSetup { TEST(RecordTickSample) { TestSetup test_setup; - CpuProfilesCollection profiles; + CpuProfilesCollection profiles(CcTest::i_isolate()->heap()); profiles.StartProfiling("", 1, false); ProfileGenerator generator(&profiles); CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); @@ -514,7 +465,7 @@ static void CheckNodeIds(ProfileNode* node, int* expectedId) { TEST(SampleIds) { TestSetup test_setup; - CpuProfilesCollection profiles; + CpuProfilesCollection profiles(CcTest::i_isolate()->heap()); profiles.StartProfiling("", 1, true); ProfileGenerator generator(&profiles); CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); @@ -562,7 +513,7 @@ TEST(SampleIds) { TEST(NoSamples) { TestSetup test_setup; - CpuProfilesCollection profiles; + CpuProfilesCollection profiles(CcTest::i_isolate()->heap()); profiles.StartProfiling("", 1, false); ProfileGenerator generator(&profiles); CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa"); @@ -701,7 +652,7 @@ TEST(RecordStackTraceAtStartProfiling) { TEST(Issue51919) { - CpuProfilesCollection collection; + CpuProfilesCollection collection(CcTest::i_isolate()->heap()); i::EmbeddedVector<char*, CpuProfilesCollection::kMaxSimultaneousProfiles> titles; for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) { @@ -831,3 +782,49 @@ TEST(LineNumber) { profiler->StopProfiling("LineNumber"); } + + + +TEST(BailoutReason) { + const char* extensions[] = { "v8/profiler" }; + v8::ExtensionConfiguration config(1, extensions); + LocalContext env(&config); + v8::HandleScope hs(env->GetIsolate()); + + v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler(); + CHECK_EQ(0, profiler->GetProfileCount()); + v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New( + "function TryCatch() {\n" + " try {\n" + " startProfiling();\n" + " } catch (e) { };\n" + "}\n" + "function TryFinally() {\n" + " try {\n" + " TryCatch();\n" + " } finally { };\n" + "}\n" + "TryFinally();\n" + "stopProfiling();")); + script->Run(); + CHECK_EQ(1, profiler->GetProfileCount()); + const v8::CpuProfile* profile = profiler->GetCpuProfile(0); + const v8::CpuProfileNode* current = profile->GetTopDownRoot(); + reinterpret_cast<ProfileNode*>( + const_cast<v8::CpuProfileNode*>(current))->Print(0); + // The tree should look like this: + // (root) + // (anonymous function) + // kTryFinally + // kTryCatch + current = PickChild(current, i::ProfileGenerator::kAnonymousFunctionName); + CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current)); + + current = PickChild(current, "TryFinally"); + CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current)); + CHECK(!strcmp("TryFinallyStatement", current->GetBailoutReason())); + + current = PickChild(current, "TryCatch"); + CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current)); + CHECK(!strcmp("TryCatchStatement", current->GetBailoutReason())); +} diff --git a/deps/v8/test/cctest/test-random-number-generator.cc b/deps/v8/test/cctest/test-random-number-generator.cc new file mode 100644 index 0000000000..93f3257003 --- /dev/null +++ b/deps/v8/test/cctest/test-random-number-generator.cc @@ -0,0 +1,92 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "v8.h" + +#include "cctest.h" +#include "utils/random-number-generator.h" + +using namespace v8::internal; + + +static const int kMaxRuns = 12345; +static const int kRandomSeeds[] = { + -1, 1, 42, 100, 1234567890, 987654321 +}; + + +TEST(NextIntWithMaxValue) { + for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) { + RandomNumberGenerator rng(kRandomSeeds[n]); + for (int max = 1; max <= kMaxRuns; ++max) { + int n = rng.NextInt(max); + CHECK_LE(0, n); + CHECK_LT(n, max); + } + } +} + + +TEST(NextBoolReturnsBooleanValue) { + for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) { + RandomNumberGenerator rng(kRandomSeeds[n]); + for (int k = 0; k < kMaxRuns; ++k) { + bool b = rng.NextBool(); + CHECK(b == false || b == true); + } + } +} + + +TEST(NextDoubleRange) { + for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) { + RandomNumberGenerator rng(kRandomSeeds[n]); + for (int k = 0; k < kMaxRuns; ++k) { + double d = rng.NextDouble(); + CHECK_LE(0.0, d); + CHECK_LT(d, 1.0); + } + } +} + + +TEST(RandomSeedFlagIsUsed) { + for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) { + FLAG_random_seed = kRandomSeeds[n]; + RandomNumberGenerator rng1; + RandomNumberGenerator rng2(kRandomSeeds[n]); + for (int k = 1; k <= kMaxRuns; ++k) { + int64_t i1, i2; + rng1.NextBytes(&i1, sizeof(i1)); + rng2.NextBytes(&i2, sizeof(i2)); + CHECK_EQ(i2, i1); + CHECK_EQ(rng2.NextInt(), rng1.NextInt()); + CHECK_EQ(rng2.NextInt(k), rng1.NextInt(k)); + CHECK_EQ(rng2.NextDouble(), rng1.NextDouble()); + } + } +} diff --git a/deps/v8/test/cctest/test-random.cc b/deps/v8/test/cctest/test-random.cc index 0a8594c04e..4227326a92 100644 --- a/deps/v8/test/cctest/test-random.cc +++ b/deps/v8/test/cctest/test-random.cc @@ -53,8 +53,8 @@ void TestSeeds(Handle<JSFunction> fun, Handle<ByteArray> seeds(context->random_seed()); SetSeeds(seeds, state0, state1); - Handle<Object> value = - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Handle<Object> value = Execution::Call( + context->GetIsolate(), fun, global, 0, NULL, &has_pending_exception); CHECK(value->IsHeapNumber()); CHECK(fun->IsOptimized()); double crankshaft_value = HeapNumber::cast(*value)->value(); @@ -69,12 +69,13 @@ void TestSeeds(Handle<JSFunction> fun, TEST(CrankshaftRandom) { v8::V8::Initialize(); // Skip test if crankshaft is disabled. - if (!V8::UseCrankshaft()) return; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - v8::Context::Scope context_scope(v8::Context::New(isolate)); + if (!Isolate::Current()->use_crankshaft()) return; + v8::Isolate* v8_isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(v8_isolate); + v8::Context::Scope context_scope(v8::Context::New(v8_isolate)); - Handle<Context> context(Isolate::Current()->context()); + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + Handle<Context> context(isolate->context()); Handle<JSObject> global(context->global_object()); Handle<ByteArray> seeds(context->random_seed()); bool has_pending_exception; @@ -88,21 +89,12 @@ TEST(CrankshaftRandom) { Handle<JSFunction> fun(JSFunction::cast(fun_object->ToObjectChecked())); // Optimize function. - Execution::Call(fun, global, 0, NULL, &has_pending_exception); - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); + Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception); if (!fun->IsOptimized()) fun->MarkForLazyRecompilation(); // Test with some random values. TestSeeds(fun, context, 0xC0C0AFFE, 0x31415926); TestSeeds(fun, context, 0x01020304, 0xFFFFFFFF); - TestSeeds(fun, context, 0x00000001, 0x00000000); - - // Test that we bail out to runtime when seeds are uninitialized (zeros). - SetSeeds(seeds, 0, 0); - Handle<Object> value = - Execution::Call(fun, global, 0, NULL, &has_pending_exception); - CHECK(value->IsHeapNumber()); - CHECK(fun->IsOptimized()); - double crankshaft_value = HeapNumber::cast(*value)->value(); - CHECK_NE(0.0, crankshaft_value); + TestSeeds(fun, context, 0x00000001, 0x00000001); } diff --git a/deps/v8/test/cctest/test-semaphore.cc b/deps/v8/test/cctest/test-semaphore.cc new file mode 100644 index 0000000000..895303f4f8 --- /dev/null +++ b/deps/v8/test/cctest/test-semaphore.cc @@ -0,0 +1,155 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <stdlib.h> + +#include "v8.h" + +#include "platform.h" +#include "cctest.h" + + +using namespace ::v8::internal; + + +class WaitAndSignalThread V8_FINAL : public Thread { + public: + explicit WaitAndSignalThread(Semaphore* semaphore) + : Thread("WaitAndSignalThread"), semaphore_(semaphore) {} + virtual ~WaitAndSignalThread() {} + + virtual void Run() V8_OVERRIDE { + for (int n = 0; n < 1000; ++n) { + semaphore_->Wait(); + bool result = semaphore_->WaitFor(TimeDelta::FromMicroseconds(1)); + ASSERT(!result); + USE(result); + semaphore_->Signal(); + } + } + + private: + Semaphore* semaphore_; +}; + + +TEST(WaitAndSignal) { + Semaphore semaphore(0); + WaitAndSignalThread t1(&semaphore); + WaitAndSignalThread t2(&semaphore); + + t1.Start(); + t2.Start(); + + // Make something available. + semaphore.Signal(); + + t1.Join(); + t2.Join(); + + semaphore.Wait(); + + bool result = semaphore.WaitFor(TimeDelta::FromMicroseconds(1)); + ASSERT(!result); + USE(result); +} + + +TEST(WaitFor) { + bool ok; + Semaphore semaphore(0); + + // Semaphore not signalled - timeout. + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(0)); + CHECK(!ok); + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(100)); + CHECK(!ok); + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)); + CHECK(!ok); + + // Semaphore signalled - no timeout. + semaphore.Signal(); + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(0)); + CHECK(ok); + semaphore.Signal(); + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(100)); + CHECK(ok); + semaphore.Signal(); + ok = semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)); + CHECK(ok); +} + + +static const char alphabet[] = "XKOAD"; +static const int kAlphabetSize = sizeof(alphabet) - 1; +static const int kBufferSize = 4096; // GCD(buffer size, alphabet size) = 1 +static char buffer[kBufferSize]; +static const int kDataSize = kBufferSize * kAlphabetSize * 10; + +static Semaphore free_space(kBufferSize); +static Semaphore used_space(0); + + +class ProducerThread V8_FINAL : public Thread { + public: + ProducerThread() : Thread("ProducerThread") {} + virtual ~ProducerThread() {} + + virtual void Run() V8_OVERRIDE { + for (int n = 0; n < kDataSize; ++n) { + free_space.Wait(); + buffer[n % kBufferSize] = alphabet[n % kAlphabetSize]; + used_space.Signal(); + } + } +}; + + +class ConsumerThread V8_FINAL : public Thread { + public: + ConsumerThread() : Thread("ConsumerThread") {} + virtual ~ConsumerThread() {} + + virtual void Run() V8_OVERRIDE { + for (int n = 0; n < kDataSize; ++n) { + used_space.Wait(); + ASSERT_EQ(static_cast<int>(alphabet[n % kAlphabetSize]), + static_cast<int>(buffer[n % kBufferSize])); + free_space.Signal(); + } + } +}; + + +TEST(ProducerConsumer) { + ProducerThread producer_thread; + ConsumerThread consumer_thread; + producer_thread.Start(); + consumer_thread.Start(); + producer_thread.Join(); + consumer_thread.Join(); +} diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index f95ff65725..099f3a05a9 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -104,7 +104,7 @@ TEST(ExternalReferenceEncoder) { isolate->stats_table()->SetCounterFunction(counter_function); v8::V8::Initialize(); - ExternalReferenceEncoder encoder; + ExternalReferenceEncoder encoder(isolate); CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode), Encode(encoder, Builtins::kArrayCode)); CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort), @@ -141,7 +141,7 @@ TEST(ExternalReferenceDecoder) { isolate->stats_table()->SetCounterFunction(counter_function); v8::V8::Initialize(); - ExternalReferenceDecoder decoder; + ExternalReferenceDecoder decoder(isolate); CHECK_EQ(AddressOf(Builtins::kArrayCode), decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode))); CHECK_EQ(AddressOf(Runtime::kAbort), @@ -228,9 +228,9 @@ void FileByteSink::WriteSpaceUsed( } -static bool WriteToFile(const char* snapshot_file) { +static bool WriteToFile(Isolate* isolate, const char* snapshot_file) { FileByteSink file(snapshot_file); - StartupSerializer ser(&file); + StartupSerializer ser(isolate, &file); ser.Serialize(); file.WriteSpaceUsed( @@ -251,19 +251,20 @@ static void Serialize() { // can be loaded from v8natives.js and their addresses can be processed. This // will clear the pending fixups array, which would otherwise contain GC roots // that would confuse the serialization/deserialization process. + v8::Isolate* isolate = v8::Isolate::GetCurrent(); { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); v8::Context::New(isolate); } - WriteToFile(FLAG_testing_serialization_file); + WriteToFile(reinterpret_cast<Isolate*>(isolate), + FLAG_testing_serialization_file); } // Test that the whole heap can be serialized. TEST(Serialize) { if (!Snapshot::HaveASnapshotToStartFrom()) { - Serializer::Enable(); + Serializer::Enable(Isolate::Current()); v8::V8::Initialize(); Serialize(); } @@ -273,7 +274,7 @@ TEST(Serialize) { // Test that heap serialization is non-destructive. TEST(SerializeTwice) { if (!Snapshot::HaveASnapshotToStartFrom()) { - Serializer::Enable(); + Serializer::Enable(Isolate::Current()); v8::V8::Initialize(); Serialize(); Serialize(); @@ -371,9 +372,9 @@ DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2, TEST(PartialSerialization) { if (!Snapshot::HaveASnapshotToStartFrom()) { - Serializer::Enable(); - v8::V8::Initialize(); Isolate* isolate = Isolate::Current(); + Serializer::Enable(isolate); + v8::V8::Initialize(); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); Heap* heap = isolate->heap(); @@ -412,14 +413,14 @@ TEST(PartialSerialization) { v8::HandleScope handle_scope(v8_isolate); v8::Local<v8::Context>::New(v8_isolate, env)->Exit(); } - env.Dispose(v8_isolate); + env.Dispose(); FileByteSink startup_sink(startup_name.start()); - StartupSerializer startup_serializer(&startup_sink); + StartupSerializer startup_serializer(isolate, &startup_sink); startup_serializer.SerializeStrongReferences(); FileByteSink partial_sink(FLAG_testing_serialization_file); - PartialSerializer p_ser(&startup_serializer, &partial_sink); + PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink); p_ser.Serialize(&raw_foo); startup_serializer.SerializeWeakReferences(); @@ -494,16 +495,17 @@ DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { int snapshot_size = 0; byte* snapshot = ReadBytes(file_name, &snapshot_size); + Isolate* isolate = Isolate::Current(); Object* root; { SnapshotByteSource source(snapshot, snapshot_size); Deserializer deserializer(&source); ReserveSpaceForSnapshot(&deserializer, file_name); - deserializer.DeserializePartial(&root); + deserializer.DeserializePartial(isolate, &root); CHECK(root->IsString()); } - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - Handle<Object> root_handle(root, Isolate::Current()); + HandleScope handle_scope(isolate); + Handle<Object> root_handle(root, isolate); Object* root2; @@ -511,7 +513,7 @@ DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { SnapshotByteSource source(snapshot, snapshot_size); Deserializer deserializer(&source); ReserveSpaceForSnapshot(&deserializer, file_name); - deserializer.DeserializePartial(&root2); + deserializer.DeserializePartial(isolate, &root2); CHECK(root2->IsString()); CHECK(*root_handle == root2); } @@ -521,9 +523,9 @@ DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { TEST(ContextSerialization) { if (!Snapshot::HaveASnapshotToStartFrom()) { - Serializer::Enable(); - v8::V8::Initialize(); Isolate* isolate = Isolate::Current(); + Serializer::Enable(isolate); + v8::V8::Initialize(); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); Heap* heap = isolate->heap(); @@ -558,14 +560,14 @@ TEST(ContextSerialization) { i::Object* raw_context = *v8::Utils::OpenPersistent(env); - env.Dispose(v8_isolate); + env.Dispose(); FileByteSink startup_sink(startup_name.start()); - StartupSerializer startup_serializer(&startup_sink); + StartupSerializer startup_serializer(isolate, &startup_sink); startup_serializer.SerializeStrongReferences(); FileByteSink partial_sink(FLAG_testing_serialization_file); - PartialSerializer p_ser(&startup_serializer, &partial_sink); + PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink); p_ser.Serialize(&raw_context); startup_serializer.SerializeWeakReferences(); @@ -605,16 +607,17 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { int snapshot_size = 0; byte* snapshot = ReadBytes(file_name, &snapshot_size); + Isolate* isolate = Isolate::Current(); Object* root; { SnapshotByteSource source(snapshot, snapshot_size); Deserializer deserializer(&source); ReserveSpaceForSnapshot(&deserializer, file_name); - deserializer.DeserializePartial(&root); + deserializer.DeserializePartial(isolate, &root); CHECK(root->IsContext()); } - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - Handle<Object> root_handle(root, Isolate::Current()); + HandleScope handle_scope(isolate); + Handle<Object> root_handle(root, isolate); Object* root2; @@ -622,7 +625,7 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { SnapshotByteSource source(snapshot, snapshot_size); Deserializer deserializer(&source); ReserveSpaceForSnapshot(&deserializer, file_name); - deserializer.DeserializePartial(&root2); + deserializer.DeserializePartial(isolate, &root2); CHECK(root2->IsContext()); CHECK(*root_handle != root2); } diff --git a/deps/v8/test/cctest/test-sockets.cc b/deps/v8/test/cctest/test-socket.cc index a9e31fc89d..47d8b17831 100644 --- a/deps/v8/test/cctest/test-sockets.cc +++ b/deps/v8/test/cctest/test-socket.cc @@ -27,6 +27,7 @@ #include "v8.h" #include "platform.h" +#include "platform/socket.h" #include "cctest.h" @@ -41,19 +42,18 @@ class SocketListenerThread : public Thread { data_size_(data_size), server_(NULL), client_(NULL), - listening_(OS::CreateSemaphore(0)) { + listening_(0) { data_ = new char[data_size_]; } ~SocketListenerThread() { // Close both sockets. delete client_; delete server_; - delete listening_; delete[] data_; } void Run(); - void WaitForListening() { listening_->Wait(); } + void WaitForListening() { listening_.Wait(); } char* data() { return data_; } private: @@ -62,7 +62,7 @@ class SocketListenerThread : public Thread { int data_size_; Socket* server_; // Server socket used for bind/accept. Socket* client_; // Single client connection used by the test. - Semaphore* listening_; // Signalled when the server socket is in listen mode. + Semaphore listening_; // Signalled when the server socket is in listen mode. }; @@ -70,7 +70,7 @@ void SocketListenerThread::Run() { bool ok; // Create the server socket and bind it to the requested port. - server_ = OS::CreateSocket(); + server_ = new Socket; server_->SetReuseAddress(true); CHECK(server_ != NULL); ok = server_->Bind(port_); @@ -79,7 +79,7 @@ void SocketListenerThread::Run() { // Listen for new connections. ok = server_->Listen(1); CHECK(ok); - listening_->Signal(); + listening_.Signal(); // Accept a connection. client_ = server_->Accept(); @@ -122,7 +122,7 @@ static void SendAndReceive(int port, char *data, int len) { listener->WaitForListening(); // Connect and write some data. - Socket* client = OS::CreateSocket(); + Socket* client = new Socket; CHECK(client != NULL); ok = client->Connect(kLocalhost, port_str); CHECK(ok); @@ -151,12 +151,6 @@ TEST(Socket) { // parallel. static const int kPort = 5859 + FlagDependentPortOffset(); - bool ok; - - // Initialize socket support. - ok = Socket::SetUp(); - CHECK(ok); - // Send and receive some data. static const int kBufferSizeSmall = 20; char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij"; @@ -180,12 +174,3 @@ TEST(Socket) { SendAndReceive(kPort, large_data, kBufferSizeLarge); delete[] large_data; } - - -TEST(HToNNToH) { - uint16_t x = 1234; - CHECK_EQ(x, Socket::NToH(Socket::HToN(x))); - - uint32_t y = 12345678; - CHECK(y == Socket::NToH(Socket::HToN(y))); -} diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc index 1f362d7e7a..3326a015de 100644 --- a/deps/v8/test/cctest/test-spaces.cc +++ b/deps/v8/test/cctest/test-spaces.cc @@ -207,7 +207,6 @@ static unsigned int Pseudorandom() { TEST(MemoryChunk) { - OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); @@ -264,7 +263,6 @@ TEST(MemoryChunk) { TEST(MemoryAllocator) { - OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); @@ -314,7 +312,6 @@ TEST(MemoryAllocator) { TEST(NewSpace) { - OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); @@ -344,7 +341,6 @@ TEST(NewSpace) { TEST(OldSpace) { - OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index 726188d917..9049df1b72 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -41,9 +41,9 @@ #include "zone-inl.h" // Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry -class RandomNumberGenerator { +class MyRandomNumberGenerator { public: - RandomNumberGenerator() { + MyRandomNumberGenerator() { init(); } @@ -133,7 +133,7 @@ class AsciiResource: public v8::String::ExternalAsciiStringResource, static void InitializeBuildingBlocks(Handle<String>* building_blocks, int bb_length, bool long_blocks, - RandomNumberGenerator* rng, + MyRandomNumberGenerator* rng, Zone* zone) { // A list of pointers that we don't have any interest in cleaning up. // If they are reachable from a root then leak detection won't complain. @@ -276,7 +276,7 @@ class ConsStringGenerationData { // Cached data. Handle<String> building_blocks_[kNumberOfBuildingBlocks]; String* empty_string_; - RandomNumberGenerator rng_; + MyRandomNumberGenerator rng_; // Stats. ConsStringStats stats_; unsigned early_terminations_; diff --git a/deps/v8/test/cctest/test-strtod.cc b/deps/v8/test/cctest/test-strtod.cc index 952f57cf3b..237d35db12 100644 --- a/deps/v8/test/cctest/test-strtod.cc +++ b/deps/v8/test/cctest/test-strtod.cc @@ -432,7 +432,7 @@ static uint32_t DeterministicRandom() { static uint32_t lo = 0; // Initialization values don't have any special meaning. (They are the result - // of two calls to random().) + // of two calls to rand().) if (hi == 0) hi = 0xbfe166e7; if (lo == 0) lo = 0x64d1c3c9; @@ -448,12 +448,13 @@ static const int kShortStrtodRandomCount = 2; static const int kLargeStrtodRandomCount = 2; TEST(RandomStrtod) { + srand(static_cast<unsigned int>(time(NULL))); char buffer[kBufferSize]; for (int length = 1; length < 15; length++) { for (int i = 0; i < kShortStrtodRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) { - buffer[pos++] = random() % 10 + '0'; + buffer[pos++] = rand() % 10 + '0'; } int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length; buffer[pos] = '\0'; @@ -466,7 +467,7 @@ TEST(RandomStrtod) { for (int i = 0; i < kLargeStrtodRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) { - buffer[pos++] = random() % 10 + '0'; + buffer[pos++] = rand() % 10 + '0'; } int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length; buffer[pos] = '\0'; diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc index b29b1dcf0c..b89f3ef8cf 100644 --- a/deps/v8/test/cctest/test-thread-termination.cc +++ b/deps/v8/test/cctest/test-thread-termination.cc @@ -171,7 +171,7 @@ class TerminatorThread : public v8::internal::Thread { // Test that a single thread of JavaScript execution can be terminated // from the side by another thread. TEST(TerminateOnlyV8ThreadFromOtherThread) { - semaphore = v8::internal::OS::CreateSemaphore(0); + semaphore = new v8::internal::Semaphore(0); TerminatorThread thread(i::Isolate::Current()); thread.Start(); @@ -192,73 +192,6 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) { } -class LoopingThread : public v8::internal::Thread { - public: - LoopingThread() : Thread("LoopingThread") { } - void Run() { - v8::Locker locker(CcTest::default_isolate()); - v8::HandleScope scope(CcTest::default_isolate()); - v8_thread_id_ = v8::V8::GetCurrentThreadId(); - v8::Handle<v8::ObjectTemplate> global = - CreateGlobalTemplate(Signal, DoLoop); - v8::Handle<v8::Context> context = - v8::Context::New(v8::Isolate::GetCurrent(), NULL, global); - v8::Context::Scope context_scope(context); - CHECK(!v8::V8::IsExecutionTerminating()); - // Run a loop that will be infinite if thread termination does not work. - v8::Handle<v8::String> source = - v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); - v8::Script::Compile(source)->Run(); - } - - int GetV8ThreadId() { return v8_thread_id_; } - - private: - int v8_thread_id_; -}; - - -// Test that multiple threads using default isolate can be terminated -// from another thread when using Lockers and preemption. -TEST(TerminateMultipleV8ThreadsDefaultIsolate) { - { - v8::Locker locker(CcTest::default_isolate()); - v8::V8::Initialize(); - v8::Locker::StartPreemption(1); - semaphore = v8::internal::OS::CreateSemaphore(0); - } - 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(CcTest::default_isolate()); - 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]; - } - { - v8::Locker locker(CcTest::default_isolate()); - v8::Locker::StopPreemption(); - } - - delete semaphore; - semaphore = NULL; -} - - int call_count = 0; @@ -391,11 +324,11 @@ void DoLoopCancelTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { // Test that a single thread of JavaScript execution can terminate // itself and then resume execution. TEST(TerminateCancelTerminateFromThreadItself) { - v8::HandleScope scope; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(TerminateCurrentThread, DoLoopCancelTerminate); - v8::Handle<v8::Context> context = - v8::Context::New(v8::Isolate::GetCurrent(), NULL, global); + v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global); v8::Context::Scope context_scope(context); CHECK(!v8::V8::IsExecutionTerminating()); v8::Handle<v8::String> source = @@ -403,4 +336,3 @@ TEST(TerminateCancelTerminateFromThreadItself) { // Check that execution completed with correct return value. CHECK(v8::Script::Compile(source)->Run()->Equals(v8_str("completed"))); } - diff --git a/deps/v8/test/cctest/test-threads.cc b/deps/v8/test/cctest/test-threads.cc index a35a88dc26..6cc5f52338 100644 --- a/deps/v8/test/cctest/test-threads.cc +++ b/deps/v8/test/cctest/test-threads.cc @@ -180,7 +180,7 @@ TEST(ThreadIdValidation) { const int kNThreads = 100; i::List<ThreadIdValidationThread*> threads(kNThreads); i::List<i::ThreadId> refs(kNThreads); - i::Semaphore* semaphore = i::OS::CreateSemaphore(0); + i::Semaphore* semaphore = new i::Semaphore(0); ThreadIdValidationThread* prev = NULL; for (int i = kNThreads - 1; i >= 0; i--) { ThreadIdValidationThread* newThread = diff --git a/deps/v8/test/cctest/test-time.cc b/deps/v8/test/cctest/test-time.cc new file mode 100644 index 0000000000..8b92d8d32a --- /dev/null +++ b/deps/v8/test/cctest/test-time.cc @@ -0,0 +1,144 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <cstdlib> + +#include "v8.h" + +#include "cctest.h" +#if V8_OS_WIN +#include "win32-headers.h" +#endif + +using namespace v8::internal; + + +TEST(TimeDeltaFromAndIn) { + CHECK(TimeDelta::FromDays(2) == TimeDelta::FromHours(48)); + CHECK(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180)); + CHECK(TimeDelta::FromMinutes(2) == TimeDelta::FromSeconds(120)); + CHECK(TimeDelta::FromSeconds(2) == TimeDelta::FromMilliseconds(2000)); + CHECK(TimeDelta::FromMilliseconds(2) == TimeDelta::FromMicroseconds(2000)); + CHECK_EQ(static_cast<int>(13), TimeDelta::FromDays(13).InDays()); + CHECK_EQ(static_cast<int>(13), TimeDelta::FromHours(13).InHours()); + CHECK_EQ(static_cast<int>(13), TimeDelta::FromMinutes(13).InMinutes()); + CHECK_EQ(static_cast<int64_t>(13), TimeDelta::FromSeconds(13).InSeconds()); + CHECK_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF()); + CHECK_EQ(static_cast<int64_t>(13), + TimeDelta::FromMilliseconds(13).InMilliseconds()); + CHECK_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF()); + CHECK_EQ(static_cast<int64_t>(13), + TimeDelta::FromMicroseconds(13).InMicroseconds()); +} + + +#if V8_OS_MACOSX +TEST(TimeDeltaFromMachTimespec) { + TimeDelta null = TimeDelta(); + CHECK(null == TimeDelta::FromMachTimespec(null.ToMachTimespec())); + TimeDelta delta1 = TimeDelta::FromMilliseconds(42); + CHECK(delta1 == TimeDelta::FromMachTimespec(delta1.ToMachTimespec())); + TimeDelta delta2 = TimeDelta::FromDays(42); + CHECK(delta2 == TimeDelta::FromMachTimespec(delta2.ToMachTimespec())); +} +#endif + + +TEST(TimeJsTime) { + Time t = Time::FromJsTime(700000.3); + CHECK_EQ(700000.3, t.ToJsTime()); +} + + +#if V8_OS_POSIX +TEST(TimeFromTimespec) { + Time null; + CHECK(null.IsNull()); + CHECK(null == Time::FromTimespec(null.ToTimespec())); + Time now = Time::Now(); + CHECK(now == Time::FromTimespec(now.ToTimespec())); + Time now_sys = Time::NowFromSystemTime(); + CHECK(now_sys == Time::FromTimespec(now_sys.ToTimespec())); + Time unix_epoch = Time::UnixEpoch(); + CHECK(unix_epoch == Time::FromTimespec(unix_epoch.ToTimespec())); + Time max = Time::Max(); + CHECK(max.IsMax()); + CHECK(max == Time::FromTimespec(max.ToTimespec())); +} + + +TEST(TimeFromTimeval) { + Time null; + CHECK(null.IsNull()); + CHECK(null == Time::FromTimeval(null.ToTimeval())); + Time now = Time::Now(); + CHECK(now == Time::FromTimeval(now.ToTimeval())); + Time now_sys = Time::NowFromSystemTime(); + CHECK(now_sys == Time::FromTimeval(now_sys.ToTimeval())); + Time unix_epoch = Time::UnixEpoch(); + CHECK(unix_epoch == Time::FromTimeval(unix_epoch.ToTimeval())); + Time max = Time::Max(); + CHECK(max.IsMax()); + CHECK(max == Time::FromTimeval(max.ToTimeval())); +} +#endif + + +#if V8_OS_WIN +TEST(TimeFromFiletime) { + Time null; + CHECK(null.IsNull()); + CHECK(null == Time::FromFiletime(null.ToFiletime())); + Time now = Time::Now(); + CHECK(now == Time::FromFiletime(now.ToFiletime())); + Time now_sys = Time::NowFromSystemTime(); + CHECK(now_sys == Time::FromFiletime(now_sys.ToFiletime())); + Time unix_epoch = Time::UnixEpoch(); + CHECK(unix_epoch == Time::FromFiletime(unix_epoch.ToFiletime())); + Time max = Time::Max(); + CHECK(max.IsMax()); + CHECK(max == Time::FromFiletime(max.ToFiletime())); +} +#endif + + +TEST(TimeTicksIsMonotonic) { + TimeTicks previous_normal_ticks; + TimeTicks previous_highres_ticks; + ElapsedTimer timer; + timer.Start(); + while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) { + TimeTicks normal_ticks = TimeTicks::Now(); + TimeTicks highres_ticks = TimeTicks::HighResNow(); + CHECK_GE(normal_ticks, previous_normal_ticks); + CHECK_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0); + CHECK_GE(highres_ticks, previous_highres_ticks); + CHECK_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0); + previous_normal_ticks = normal_ticks; + previous_highres_ticks = highres_ticks; + } +} diff --git a/deps/v8/test/cctest/test-unique.cc b/deps/v8/test/cctest/test-unique.cc new file mode 100644 index 0000000000..1d268580ed --- /dev/null +++ b/deps/v8/test/cctest/test-unique.cc @@ -0,0 +1,488 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <stdlib.h> + +#include "v8.h" + +#include "factory.h" +#include "global-handles.h" +#include "unique.h" +#include "cctest.h" + +using namespace v8::internal; + +template <class T, class U> +void CheckHashCodeEqual(Unique<T> a, Unique<U> b) { + int64_t hasha = static_cast<int64_t>(a.Hashcode()); + int64_t hashb = static_cast<int64_t>(b.Hashcode()); + CHECK_NE(static_cast<int64_t>(0), hasha); + CHECK_NE(static_cast<int64_t>(0), hashb); + CHECK_EQ(hasha, hashb); +} + + +template <class T, class U> +void CheckHashCodeNotEqual(Unique<T> a, Unique<U> b) { + int64_t hasha = static_cast<int64_t>(a.Hashcode()); + int64_t hashb = static_cast<int64_t>(b.Hashcode()); + CHECK_NE(static_cast<int64_t>(0), hasha); + CHECK_NE(static_cast<int64_t>(0), hashb); + CHECK_NE(hasha, hashb); +} + + +TEST(UniqueCreate) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Handle<String> A = factory->InternalizeUtf8String("A"); + Unique<String> HA(A); + + CHECK(*HA.handle() == *A); + CHECK_EQ(*A, *HA.handle()); + + Unique<String> HA2(A); + + CheckHashCodeEqual(HA, HA2); + CHECK(HA == HA2); + CHECK_EQ(*HA.handle(), *HA2.handle()); + + CHECK(HA2 == HA); + CHECK_EQ(*HA2.handle(), *HA.handle()); + + Handle<String> B = factory->InternalizeUtf8String("B"); + Unique<String> HB(B); + + CheckHashCodeNotEqual(HA, HB); + CHECK(HA != HB); + CHECK_NE(*HA.handle(), *HB.handle()); + + CHECK(HB != HA); + CHECK_NE(*HB.handle(), *HA.handle()); + + // TODO(titzer): check that Unique properly survives a GC. +} + + +TEST(UniqueSubsume) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Handle<String> A = factory->InternalizeUtf8String("A"); + Unique<String> HA(A); + + CHECK(*HA.handle() == *A); + CHECK_EQ(*A, *HA.handle()); + + Unique<Object> HO = HA; // Here comes the subsumption, boys. + + CheckHashCodeEqual(HA, HO); + CHECK(HA == HO); + CHECK_EQ(*HA.handle(), *HO.handle()); + + CHECK(HO == HA); + CHECK_EQ(*HO.handle(), *HA.handle()); +} + + +TEST(UniqueSet_Add) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + + Zone zone(isolate); + + UniqueSet<String>* set = new(&zone) UniqueSet<String>(); + + CHECK_EQ(0, set->size()); + set->Add(A, &zone); + CHECK_EQ(1, set->size()); + set->Add(A, &zone); + CHECK_EQ(1, set->size()); + set->Add(B, &zone); + CHECK_EQ(2, set->size()); + set->Add(C, &zone); + CHECK_EQ(3, set->size()); + set->Add(C, &zone); + CHECK_EQ(3, set->size()); + set->Add(B, &zone); + CHECK_EQ(3, set->size()); + set->Add(A, &zone); + CHECK_EQ(3, set->size()); +} + + +template <class T> +static void CHECK_SETS( + UniqueSet<T>* set1, UniqueSet<T>* set2, bool expected) { + CHECK(set1->Equals(set1)); + CHECK(set2->Equals(set2)); + CHECK(expected == set1->Equals(set2)); + CHECK(expected == set2->Equals(set1)); +} + + +TEST(UniqueSet_Equals) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + + Zone zone(isolate); + + UniqueSet<String>* set1 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* set2 = new(&zone) UniqueSet<String>(); + + CHECK_SETS(set1, set2, true); + + set1->Add(A, &zone); + + CHECK_SETS(set1, set2, false); + + set2->Add(A, &zone); + + CHECK_SETS(set1, set2, true); + + set1->Add(B, &zone); + + CHECK_SETS(set1, set2, false); + + set2->Add(C, &zone); + + CHECK_SETS(set1, set2, false); + + set1->Add(C, &zone); + + CHECK_SETS(set1, set2, false); + + set2->Add(B, &zone); + + CHECK_SETS(set1, set2, true); +} + + +TEST(UniqueSet_IsSubset1) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + + Zone zone(isolate); + + UniqueSet<String>* set1 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* set2 = new(&zone) UniqueSet<String>(); + + CHECK(set1->IsSubset(set2)); + CHECK(set2->IsSubset(set1)); + + set1->Add(A, &zone); + + CHECK(!set1->IsSubset(set2)); + CHECK(set2->IsSubset(set1)); + + set2->Add(B, &zone); + + CHECK(!set1->IsSubset(set2)); + CHECK(!set2->IsSubset(set1)); + + set2->Add(A, &zone); + + CHECK(set1->IsSubset(set2)); + CHECK(!set2->IsSubset(set1)); + + set1->Add(B, &zone); + + CHECK(set1->IsSubset(set2)); + CHECK(set2->IsSubset(set1)); +} + + +TEST(UniqueSet_IsSubset2) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + Unique<String> D(factory->InternalizeUtf8String("D")); + Unique<String> E(factory->InternalizeUtf8String("E")); + Unique<String> F(factory->InternalizeUtf8String("F")); + Unique<String> G(factory->InternalizeUtf8String("G")); + + Zone zone(isolate); + + UniqueSet<String>* set1 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* set2 = new(&zone) UniqueSet<String>(); + + set1->Add(A, &zone); + set1->Add(C, &zone); + set1->Add(E, &zone); + + set2->Add(A, &zone); + set2->Add(B, &zone); + set2->Add(C, &zone); + set2->Add(D, &zone); + set2->Add(E, &zone); + set2->Add(F, &zone); + + CHECK(set1->IsSubset(set2)); + CHECK(!set2->IsSubset(set1)); + + set1->Add(G, &zone); + + CHECK(!set1->IsSubset(set2)); + CHECK(!set2->IsSubset(set1)); +} + + +template <class T> +static UniqueSet<T>* MakeSet(Zone* zone, int which, Unique<T>* elements) { + UniqueSet<T>* set = new(zone) UniqueSet<T>(); + for (int i = 0; i < 32; i++) { + if ((which & (1 << i)) != 0) set->Add(elements[i], zone); + } + return set; +} + + +TEST(UniqueSet_IsSubsetExhaustive) { + const int kSetSize = 6; + + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Zone zone(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + Unique<String> D(factory->InternalizeUtf8String("D")); + Unique<String> E(factory->InternalizeUtf8String("E")); + Unique<String> F(factory->InternalizeUtf8String("F")); + Unique<String> G(factory->InternalizeUtf8String("G")); + + Unique<String> elements[] = { + A, B, C, D, E, F, G + }; + + // Exhaustively test all sets with <= 6 elements. + for (int i = 0; i < (1 << kSetSize); i++) { + for (int j = 0; j < (1 << kSetSize); j++) { + UniqueSet<String>* set1 = MakeSet(&zone, i, elements); + UniqueSet<String>* set2 = MakeSet(&zone, j, elements); + + CHECK(((i & j) == i) == set1->IsSubset(set2)); + } + } +} + + +TEST(UniqueSet_Intersect1) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + + Zone zone(isolate); + + UniqueSet<String>* set1 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* set2 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* result; + + CHECK(set1->IsSubset(set2)); + CHECK(set2->IsSubset(set1)); + + set1->Add(A, &zone); + + result = set1->Intersect(set2, &zone); + + CHECK_EQ(0, result->size()); + CHECK(set2->Equals(result)); + + set2->Add(A, &zone); + + result = set1->Intersect(set2, &zone); + + CHECK_EQ(1, result->size()); + CHECK(set1->Equals(result)); + CHECK(set2->Equals(result)); + + set2->Add(B, &zone); + set2->Add(C, &zone); + + result = set1->Intersect(set2, &zone); + + CHECK_EQ(1, result->size()); + CHECK(set1->Equals(result)); +} + + +TEST(UniqueSet_IntersectExhaustive) { + const int kSetSize = 6; + + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Zone zone(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + Unique<String> D(factory->InternalizeUtf8String("D")); + Unique<String> E(factory->InternalizeUtf8String("E")); + Unique<String> F(factory->InternalizeUtf8String("F")); + Unique<String> G(factory->InternalizeUtf8String("G")); + + Unique<String> elements[] = { + A, B, C, D, E, F, G + }; + + // Exhaustively test all sets with <= 6 elements. + for (int i = 0; i < (1 << kSetSize); i++) { + for (int j = 0; j < (1 << kSetSize); j++) { + UniqueSet<String>* set1 = MakeSet(&zone, i, elements); + UniqueSet<String>* set2 = MakeSet(&zone, j, elements); + + UniqueSet<String>* result = set1->Intersect(set2, &zone); + UniqueSet<String>* expected = MakeSet(&zone, i & j, elements); + + CHECK(result->Equals(expected)); + CHECK(expected->Equals(result)); + } + } +} + + +TEST(UniqueSet_Union1) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + + Zone zone(isolate); + + UniqueSet<String>* set1 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* set2 = new(&zone) UniqueSet<String>(); + UniqueSet<String>* result; + + CHECK(set1->IsSubset(set2)); + CHECK(set2->IsSubset(set1)); + + set1->Add(A, &zone); + + result = set1->Union(set2, &zone); + + CHECK_EQ(1, result->size()); + CHECK(set1->Equals(result)); + + set2->Add(A, &zone); + + result = set1->Union(set2, &zone); + + CHECK_EQ(1, result->size()); + CHECK(set1->Equals(result)); + CHECK(set2->Equals(result)); + + set2->Add(B, &zone); + set2->Add(C, &zone); + + result = set1->Union(set2, &zone); + + CHECK_EQ(3, result->size()); + CHECK(set2->Equals(result)); +} + + +TEST(UniqueSet_UnionExhaustive) { + const int kSetSize = 6; + + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + Factory* factory = isolate->factory(); + HandleScope sc(isolate); + + Zone zone(isolate); + + Unique<String> A(factory->InternalizeUtf8String("A")); + Unique<String> B(factory->InternalizeUtf8String("B")); + Unique<String> C(factory->InternalizeUtf8String("C")); + Unique<String> D(factory->InternalizeUtf8String("D")); + Unique<String> E(factory->InternalizeUtf8String("E")); + Unique<String> F(factory->InternalizeUtf8String("F")); + Unique<String> G(factory->InternalizeUtf8String("G")); + + Unique<String> elements[] = { + A, B, C, D, E, F, G + }; + + // Exhaustively test all sets with <= 6 elements. + for (int i = 0; i < (1 << kSetSize); i++) { + for (int j = 0; j < (1 << kSetSize); j++) { + UniqueSet<String>* set1 = MakeSet(&zone, i, elements); + UniqueSet<String>* set2 = MakeSet(&zone, j, elements); + + UniqueSet<String>* result = set1->Union(set2, &zone); + UniqueSet<String>* expected = MakeSet(&zone, i | j, elements); + + CHECK(result->Equals(expected)); + CHECK(expected->Equals(result)); + } + } +} + diff --git a/deps/v8/test/cctest/test-utils.cc b/deps/v8/test/cctest/test-utils.cc index 541c42338c..feff477933 100644 --- a/deps/v8/test/cctest/test-utils.cc +++ b/deps/v8/test/cctest/test-utils.cc @@ -140,7 +140,6 @@ void TestMemMove(byte* area1, TEST(MemMove) { v8::V8::Initialize(); - OS::SetUp(); byte* area1 = new byte[kAreaSize]; byte* area2 = new byte[kAreaSize]; byte* area3 = new byte[kAreaSize]; diff --git a/deps/v8/test/cctest/test-weakmaps.cc b/deps/v8/test/cctest/test-weakmaps.cc index 9044f17e4e..932b06b850 100644 --- a/deps/v8/test/cctest/test-weakmaps.cc +++ b/deps/v8/test/cctest/test-weakmaps.cc @@ -69,7 +69,7 @@ static void WeakPointerCallback(v8::Isolate* isolate, void* id) { ASSERT(id == reinterpret_cast<void*>(1234)); NumberOfWeakCalls++; - handle->Dispose(isolate); + handle->Dispose(); } diff --git a/deps/v8/test/cctest/test-weaksets.cc b/deps/v8/test/cctest/test-weaksets.cc index 707f903284..aff4c7fcbe 100644 --- a/deps/v8/test/cctest/test-weaksets.cc +++ b/deps/v8/test/cctest/test-weaksets.cc @@ -69,7 +69,7 @@ static void WeakPointerCallback(v8::Isolate* isolate, void* id) { ASSERT(id == reinterpret_cast<void*>(1234)); NumberOfWeakCalls++; - handle->Dispose(isolate); + handle->Dispose(); } diff --git a/deps/v8/test/mjsunit/array-push-non-smi-value.js b/deps/v8/test/mjsunit/array-push-non-smi-value.js new file mode 100644 index 0000000000..460dd2a911 --- /dev/null +++ b/deps/v8/test/mjsunit/array-push-non-smi-value.js @@ -0,0 +1,36 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Check pushes of non-SMI values. +var a = []; +function func() { + return a.push(0x40000000) > 60; +} + +assertFalse(func()); +assertFalse(func()); +assertFalse(func()); diff --git a/deps/v8/test/mjsunit/array-store-and-grow.js b/deps/v8/test/mjsunit/array-store-and-grow.js index a03a753e44..5ac95e9b3a 100644 --- a/deps/v8/test/mjsunit/array-store-and-grow.js +++ b/deps/v8/test/mjsunit/array-store-and-grow.js @@ -187,6 +187,7 @@ array_store_1(a, 0, 0.5); assertEquals(0.5, a[0]); assertEquals(0.5, array_store_1([], 0, 0.5)); + // Verify that a grow store will deoptimize if the max gap (difference between // the end of an array capacity and a new index) is passed. The wrapper is to // make sure array_store_10 isn't inlined. @@ -207,3 +208,49 @@ assertEquals(0.5, array_store_1([], 0, 0.5)); %ClearFunctionTypeFeedback(grow_store); })(); + +// Verify that a polymorphic store and grow IC when crankshafted is still +// a grow IC (earlier it would revert to a standard store in the polymorphic +// case). +(function() { + function f(o, k, v) { + o[k] = v; + } + + a = [3.5]; + f(a, 1, "hi"); // DOUBLE packed array -> tagged packed grow + a = {}; + a.p = "property"; + a[0] = 1; + f(a, 0, 5.4); + + %OptimizeFunctionOnNextCall(f); + // Should be a polymorphic grow stub. If not a grow stub it will deopt. + f(new Array("hi"), 1, 3); + assertOptimized(f); + %ClearFunctionTypeFeedback(f); +})(); + + +// Now verify that a polymorphic store (non-growing) IC when crankshafted WILL +// deopt if you pass an element out of bounds. +(function() { + function f(o, k, v) { + o[k] = v; + } + + a = [3.5]; + f(a, 0, "hi"); // DOUBLE packed array -> tagged packed grow + a = {}; + a.p = "property"; + a[0] = 1; + f(a, 0, 5.4); + + %OptimizeFunctionOnNextCall(f); + f(new Array("hi"), 0, 3); + assertOptimized(f); + // An attempt to grow should cause deopt + f(new Array("hi"), 1, 3); + assertUnoptimized(f); + %ClearFunctionTypeFeedback(f); +})(); diff --git a/deps/v8/test/mjsunit/assert-opt-and-deopt.js b/deps/v8/test/mjsunit/assert-opt-and-deopt.js index bfd2f3f489..d653bb5905 100644 --- a/deps/v8/test/mjsunit/assert-opt-and-deopt.js +++ b/deps/v8/test/mjsunit/assert-opt-and-deopt.js @@ -25,10 +25,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax +// Flags: --allow-natives-syntax --noconcurrent-recompilation -if (%IsParallelRecompilationSupported()) { - print("Parallel recompilation is turned on after all. Skipping this test."); +if (%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is turned on after all. Skipping this test."); quit(); } diff --git a/deps/v8/test/mjsunit/compiler/escape-analysis.js b/deps/v8/test/mjsunit/compiler/escape-analysis.js index 9776f67ccf..74e638a538 100644 --- a/deps/v8/test/mjsunit/compiler/escape-analysis.js +++ b/deps/v8/test/mjsunit/compiler/escape-analysis.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --use-escape-analysis +// Flags: --allow-natives-syntax --use-escape-analysis --expose-gc // Test stores on a join path. @@ -132,3 +132,142 @@ delete deopt.deopt; func(); func(); })(); + + +// Test deoptimization with captured objects on operand stack. +(function testDeoptOperand() { + var deopt = { deopt:false }; + function constructor1() { + this.a = 1.0; + this.b = 2.3; + deopt.deopt; + assertEquals(1.0, this.a); + assertEquals(2.3, this.b); + this.b = 2.7; + this.c = 3.0; + this.d = 4.5; + } + function constructor2() { + this.e = 5.0; + this.f = new constructor1(); + assertEquals(1.0, this.f.a); + assertEquals(2.7, this.f.b); + assertEquals(3.0, this.f.c); + assertEquals(4.5, this.f.d); + assertEquals(5.0, this.e); + this.e = 5.9; + this.g = 6.7; + } + function func() { + var o = new constructor2(); + assertEquals(1.0, o.f.a); + assertEquals(2.7, o.f.b); + assertEquals(3.0, o.f.c); + assertEquals(4.5, o.f.d); + assertEquals(5.9, o.e); + assertEquals(6.7, o.g); + } + func(); func(); + %OptimizeFunctionOnNextCall(func); + func(); func(); + delete deopt.deopt; + func(); func(); +})(); + + +// Test map checks on captured objects. +(function testMapCheck() { + var sum = 0; + function getter() { return 27; } + function setter(v) { sum += v; } + function constructor() { + this.x = 23; + this.y = 42; + } + function check(x, y) { + var o = new constructor(); + assertEquals(x, o.x); + assertEquals(y, o.y); + } + var monkey = Object.create(null, { + x: { get:getter, set:setter }, + y: { get:getter, set:setter } + }); + check(23, 42); check(23, 42); + %OptimizeFunctionOnNextCall(check); + check(23, 42); check(23, 42); + constructor.prototype = monkey; + check(27, 27); check(27, 27); + assertEquals(130, sum); +})(); + + +// Test OSR into a loop with captured objects. +(function testOSR() { + function constructor() { + this.a = 23; + } + function osr1(length) { + assertEquals(23, (new constructor()).a); + var result = 0; + for (var i = 0; i < length; i++) { + result = (result + i) % 99; + } + return result; + } + function osr2(length) { + var result = 0; + for (var i = 0; i < length; i++) { + result = (result + i) % 99; + } + assertEquals(23, (new constructor()).a); + return result; + } + function osr3(length) { + var result = 0; + var o = new constructor(); + for (var i = 0; i < length; i++) { + result = (result + i) % 99; + } + assertEquals(23, o.a); + return result; + } + function test(closure) { + assertEquals(45, closure(10)); + assertEquals(45, closure(10)); + assertEquals(10, closure(50000)); + } + test(osr1); + test(osr2); + test(osr3); +})(); + + +// Test out-of-bounds access on captured objects. +(function testOOB() { + function cons1() { + this.x = 1; + this.y = 2; + this.z = 3; + } + function cons2() { + this.a = 7; + } + function oob(constructor, branch) { + var o = new constructor(); + if (branch) { + return o.a; + } else { + return o.z; + } + } + assertEquals(3, oob(cons1, false)); + assertEquals(3, oob(cons1, false)); + assertEquals(7, oob(cons2, true)); + assertEquals(7, oob(cons2, true)); + gc(); // Clears type feedback of constructor call. + assertEquals(7, oob(cons2, true)); + assertEquals(7, oob(cons2, true)); + %OptimizeFunctionOnNextCall(oob); + assertEquals(7, oob(cons2, true)); +})(); diff --git a/deps/v8/test/mjsunit/compiler/increment-typefeedback.js b/deps/v8/test/mjsunit/compiler/increment-typefeedback.js new file mode 100644 index 0000000000..798959296c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/increment-typefeedback.js @@ -0,0 +1,39 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +function f(x) { + x++; + return x; +} + +f(0.5); +f(0.5); +%OptimizeFunctionOnNextCall(f); +f(0.5); +assertOptimized(f); diff --git a/deps/v8/test/mjsunit/compiler/optimized-for-in.js b/deps/v8/test/mjsunit/compiler/optimized-for-in.js index cb8c66df9f..9c756aafa7 100644 --- a/deps/v8/test/mjsunit/compiler/optimized-for-in.js +++ b/deps/v8/test/mjsunit/compiler/optimized-for-in.js @@ -26,6 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --optimize-for-in --allow-natives-syntax +// Flags: --no-concurrent-osr // Test for-in support in Crankshaft. For simplicity this tests assumes certain // fixed iteration order for properties and will have to be adjusted if V8 diff --git a/deps/v8/test/mjsunit/compiler/osr-assert.js b/deps/v8/test/mjsunit/compiler/osr-assert.js new file mode 100644 index 0000000000..94b901fd4f --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/osr-assert.js @@ -0,0 +1,41 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --use-osr + +function f(x, b, c) { + var outer = 1000000; + var a = 1; + while (outer > 0) { + a = a + 5; + assertEquals(b + 1, c); + outer--; + } + return a + 4; +} + +assertEquals(5000005, f(5, "122", "1221")); diff --git a/deps/v8/test/mjsunit/compiler/osr-sar.js b/deps/v8/test/mjsunit/compiler/osr-sar.js new file mode 100644 index 0000000000..fd68b98a45 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/osr-sar.js @@ -0,0 +1,49 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +function test() { + // Loop to force OSR. + var j = 0; + for (var i = 0; i < 80000; i++) { + j++; + } + + function SarShr(val) { + return val >> (-2 >>> 0); + } + + var K3 = 0x80000000; + assertEquals(-2, SarShr(K3 | 0)); + assertEquals(-2, SarShr(K3 | 0)); + %OptimizeFunctionOnNextCall(SarShr); + assertEquals(-2, SarShr(K3 | 0)); +} + +test(); +//test(); diff --git a/deps/v8/test/mjsunit/compiler/osr-uint32.js b/deps/v8/test/mjsunit/compiler/osr-uint32.js new file mode 100644 index 0000000000..d6fcae546c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/osr-uint32.js @@ -0,0 +1,39 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Loop to force OSR. +var j = 0; +for (var i = 0; i < 80000; i++) { + j++; +} + +function SarShr(val) { + return val >> (-2 >>> 0); +} + +var K3 = 0x80000000; +assertEquals(-2, SarShr(K3 | 0)); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-298392.js b/deps/v8/test/mjsunit/compiler/osr-warm.js index 8370654b6c..65ada1e114 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-298392.js +++ b/deps/v8/test/mjsunit/compiler/osr-warm.js @@ -25,27 +25,26 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -function foo() { - return [[1,2,3], [5,6,6]]; -} +// Flags: --use-osr -function bar() { - return ["foo", "bar"]; +function f1(x) { + while (x > 0) { + x--; + } + return x; } -function baz() { - return [foo(), bar(), foo(), bar()]; -} +assertEquals(0, f1(1)); +assertEquals(0, f1(10000000)); -function thingy() { - var result = []; - for (var i = 0; i < 50000; ++i) { - result.push(baz()); +function f2(x) { + var sum = 1; + while (x > 0) { + x--; + sum++; } - return result; + return sum; } -var size = thingy().length; -if (size != 50000) { - throw "Error: bad size: " + size; -} +assertEquals(2, f2(1)); +assertEquals(10000001, f2(10000000)); diff --git a/deps/v8/test/mjsunit/compiler/parallel-proto-change.js b/deps/v8/test/mjsunit/compiler/parallel-proto-change.js index 25ea3b59df..7602279893 100644 --- a/deps/v8/test/mjsunit/compiler/parallel-proto-change.js +++ b/deps/v8/test/mjsunit/compiler/parallel-proto-change.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --allow-natives-syntax -// Flags: --parallel-recompilation --parallel-recompilation-delay=50 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=50 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -41,11 +41,11 @@ o.__proto__ = { __proto__: { bar: function() { return 1; } } }; assertEquals(1, f(o)); assertEquals(1, f(o)); -// Mark for parallel optimization. -%OptimizeFunctionOnNextCall(f, "parallel"); -// Trigger optimization in the parallel thread. +// Mark for concurrent optimization. +%OptimizeFunctionOnNextCall(f, "concurrent"); +// Trigger optimization in the background thread. assertEquals(1, f(o)); -// While parallel recompilation is running, optimization not yet done. +// While concurrent recompilation is running, optimization not yet done. assertUnoptimized(f, "no sync"); // Change the prototype chain during optimization to trigger map invalidation. o.__proto__.__proto__ = { bar: function() { return 2; } }; diff --git a/deps/v8/test/mjsunit/debug-script.js b/deps/v8/test/mjsunit/debug-script.js index 6e673f71c0..1cbdb376cc 100644 --- a/deps/v8/test/mjsunit/debug-script.js +++ b/deps/v8/test/mjsunit/debug-script.js @@ -59,9 +59,9 @@ for (i = 0; i < scripts.length; i++) { } // This has to be updated if the number of native scripts change. -assertEquals(16, named_native_count); -// Only the 'gc' and (depending on flags) the 'i18n' extensions are loaded. -assertTrue(extension_count == 1 || extension_count == 2); +assertTrue(named_native_count == 16 || named_native_count == 17); +// Only the 'gc' extension is loaded. +assertEquals(1, extension_count); // This script and mjsunit.js has been loaded. If using d8, d8 loads // a normal script during startup too. assertTrue(normal_count == 2 || normal_count == 3); diff --git a/deps/v8/test/mjsunit/debug-step-4-in-frame.js b/deps/v8/test/mjsunit/debug-step-4-in-frame.js new file mode 100644 index 0000000000..65ac4902dd --- /dev/null +++ b/deps/v8/test/mjsunit/debug-step-4-in-frame.js @@ -0,0 +1,132 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +// Tests how debugger can step over not necessarily in the top frame. + +// Simple 3 functions, that protocol their execution state in global +// variable state. +var state; + +function f() { + var a = 1978; + for (state[2] = 0; state[2] < 5; state[2]++) { + void String(a); + } +} +function g() { + for (state[1] = 0; state[1] < 5; state[1]++) { + f(); + } +} +function h() { + state = [-1, -1, -1]; + for (state[0] = 0; state[0] < 5; state[0]++) { + g(); + } +} + +function TestCase(frame_index, step_count, expected_final_state) { + print("Test case, parameters " + frame_index + "/" + step_count); + + var listener_exception = null; + var state_snapshot; + var listener_state; + var bp; + + function listener(event, exec_state, event_data, data) { + print("Here ("+event+"/"+listener_state+"): " + + exec_state.frame(0).sourceLineText()); + try { + if (event == Debug.DebugEvent.Break) { + if (listener_state == 0) { + Debug.clearBreakPoint(bp); + var context_frame; + if (frame_index !== undefined) { + context_frame = exec_state.frame(frame_index); + } + exec_state.prepareStep(Debug.StepAction.StepNext, + step_count, context_frame); + listener_state = 1; + } else if (listener_state == 1) { + state_snapshot = String(state); + print("State: " + state_snapshot); + Debug.setListener(null); + listener_state = 2; + } + } + } catch (e) { + listener_exception = e; + } + } + + + // Add the debug event listener. + listener_state = 0; + Debug.setListener(listener); + bp = Debug.setBreakPoint(f, 1); + + h(); + Debug.setListener(null); + if (listener_exception !== null) { + print("Exception caught: " + listener_exception); + assertUnreachable(); + } + + assertEquals(expected_final_state, state_snapshot); +} + + +// Warm-up -- make sure all is compiled and ready for breakpoint. +h(); + + +// Stepping in the default (top) frame. +TestCase(undefined, 0, "0,0,-1"); +TestCase(undefined, 1, "0,0,-1"); +TestCase(undefined, 2, "0,0,0"); +TestCase(undefined, 5, "0,0,1"); +TestCase(undefined, 8, "0,0,3"); + +// Stepping in the frame #0 (should be exactly the same as above). +TestCase(0, 0, "0,0,-1"); +TestCase(0, 1, "0,0,-1"); +TestCase(0, 2, "0,0,0"); +TestCase(0, 5, "0,0,1"); +TestCase(0, 8, "0,0,3"); + +// Stepping in the frame #1. +TestCase(1, 0, "0,0,5"); +TestCase(1, 3, "0,1,5"); +TestCase(1, 8, "0,4,5"); + +// Stepping in the frame #2. +TestCase(2, 3, "1,5,5"); +TestCase(2, 8, "4,5,5"); diff --git a/deps/v8/test/mjsunit/debug-stepin-positions.js b/deps/v8/test/mjsunit/debug-stepin-positions.js index 482e21be4d..e6d8204611 100644 --- a/deps/v8/test/mjsunit/debug-stepin-positions.js +++ b/deps/v8/test/mjsunit/debug-stepin-positions.js @@ -30,26 +30,35 @@ Debug = debug.Debug function DebuggerStatement() { - debugger; + debugger; /*pause*/ } -function TestCase(fun) { +function TestCase(fun, frame_number) { var exception = false; var codeSnippet = undefined; var resultPositions = undefined; function listener(event, exec_state, event_data, data) { try { - if (event == Debug.DebugEvent.Break) { + if (event == Debug.DebugEvent.Break || + event == Debug.DebugEvent.Exception) { Debug.setListener(null); - - var secondFrame = exec_state.frame(1); - codeSnippet = secondFrame.sourceLineText(); - resultPositions = secondFrame.stepInPositions(); + assertHasLineMark(/pause/, exec_state.frame(0)); + assertHasLineMark(/positions/, exec_state.frame(frame_number)); + var frame = exec_state.frame(frame_number); + codeSnippet = frame.sourceLineText(); + resultPositions = frame.stepInPositions(); } } catch (e) { exception = e } + + function assertHasLineMark(mark, frame) { + var line = frame.sourceLineText(); + if (!mark.exec(frame.sourceLineText())) { + throw new Error("Line " + line + " should contain mark " + mark); + } + } } Debug.setListener(listener); @@ -101,26 +110,98 @@ function TestCase(fun) { decoratedResult); } +function TestCaseWithDebugger(fun) { + TestCase(fun, 1); +} + +function TestCaseWithBreakpoint(fun, line_number, frame_number) { + var breakpointId = Debug.setBreakPoint(fun, line_number); + TestCase(fun, frame_number); + Debug.clearBreakPoint(breakpointId); +} + +function TestCaseWithException(fun, frame_number) { + Debug.setBreakOnException(); + TestCase(fun, frame_number); + Debug.clearBreakOnException(); +} + // Test cases. +// Step in position, when the function call that we are standing at is already +// being executed. +var fun = function() { + function g(p) { + throw String(p); /*pause*/ + } + try { + var res = [ g(1), /*#*/g(2) ]; /*positions*/ + } catch (e) { + } +}; +TestCaseWithBreakpoint(fun, 2, 1); +TestCaseWithException(fun, 1); + + +// Step in position, when the function call that we are standing at is raising +// an exception. +var fun = function() { + var o = { + g: function(p) { + throw p; + } + }; + try { + var res = [ /*#*/f(1), /*#*/g(2) ]; /*pause, positions*/ + } catch (e) { + } +}; +TestCaseWithException(fun, 0); + + +// Step-in position, when already paused almost on the first call site. +var fun = function() { + function g(p) { + throw p; + } + try { + var res = [ /*#*/g(Math.rand), /*#*/g(2) ]; /*pause, positions*/ + } catch (e) { + } +}; +TestCaseWithBreakpoint(fun, 5, 0); + +// Step-in position, when already paused on the first call site. +var fun = function() { + function g() { + throw "Debug"; + } + try { + var res = [ /*#*/g(), /*#*/g() ]; /*pause, positions*/ + } catch (e) { + } +}; +TestCaseWithBreakpoint(fun, 5, 0); + + // Method calls. var fun = function() { var data = { a: function() {} }; - var res = [ DebuggerStatement(), data./*#*/a(), data[/*#*/String("a")]/*#*/(), data["a"]/*#*/(), data.a, data["a"] ]; + var res = [ DebuggerStatement(), data./*#*/a(), data[/*#*/String("a")]/*#*/(), data["a"]/*#*/(), data.a, data["a"] ]; /*positions*/ }; -TestCase(fun); +TestCaseWithDebugger(fun); // Function call on a value. var fun = function() { function g(p) { return g; } - var res = [ DebuggerStatement(), /*#*/g(2), /*#*/g(2)/*#*/(3), /*#*/g(0)/*#*/(0)/*#*/(g) ]; + var res = [ DebuggerStatement(), /*#*/g(2), /*#*/g(2)/*#*/(3), /*#*/g(0)/*#*/(0)/*#*/(g) ]; /*positions*/ }; -TestCase(fun); +TestCaseWithDebugger(fun); // Local function call, closure function call, // local function construction call. @@ -128,15 +209,17 @@ var fun = (function(p) { return function() { function f(a, b) { } - var res = /*#*/f(DebuggerStatement(), /*#*/p(/*#*/new f())); + var res = /*#*/f(DebuggerStatement(), /*#*/p(/*#*/new f())); /*positions*/ }; })(Object); -TestCase(fun); +TestCaseWithDebugger(fun); // Global function, global object construction, calls before pause point. var fun = (function(p) { return function() { - var res = [ Math.abs(new Object()), DebuggerStatement(), Math./*#*/abs(4), /*#*/new Object()./*#*/toString() ]; + var res = [ Math.abs(new Object()), DebuggerStatement(), Math./*#*/abs(4), /*#*/new Object()./*#*/toString() ]; /*positions*/ }; })(Object); -TestCase(fun); +TestCaseWithDebugger(fun); + + diff --git a/deps/v8/test/mjsunit/external-array-no-sse2.js b/deps/v8/test/mjsunit/external-array-no-sse2.js index 11e61ba186..575a8b53cf 100644 --- a/deps/v8/test/mjsunit/external-array-no-sse2.js +++ b/deps/v8/test/mjsunit/external-array-no-sse2.js @@ -679,3 +679,37 @@ boo(built_in_array, 0, 2.5); assertEquals(2.5, goo(built_in_array, 0)); %ClearFunctionTypeFeedback(goo); %ClearFunctionTypeFeedback(boo); + +// Check all int range edge cases +function checkRange() { + var e32 = Math.pow(2,32); var e31 = Math.pow(2,31); + var e16 = Math.pow(2,16); var e15 = Math.pow(2,15); + var e8 = Math.pow(2,8); var e7 = Math.pow(2,7); + var a7 = new Uint32Array(2); var a71 = new Int32Array(2); + var a72 = new Uint16Array(2); var a73 = new Int16Array(2); + var a74 = new Uint8Array(2); var a75 = new Int8Array(2); + for (i = 1; i <= Math.pow(2,33); i *= 2) { + var j = i-1; + a7[0] = i; a71[0] = i; a72[0] = i; a73[0] = i; a74[0] = i; a75[0] = i; + a7[1] = j; a71[1] = j; a72[1] = j; a73[1] = j; a74[1] = j; a75[1] = j; + + if (i < e32) { assertEquals(a7[0], i); } else { assertEquals(a7[0], 0); } + if (j < e32) { assertEquals(a7[1], j); } else { assertEquals(a7[1],e32-1); } + if (i < e31) { assertEquals(a71[0], i); } else { + assertEquals(a71[0], (i < e32) ? -e31 : 0 ); } + if (j < e31) { assertEquals(a71[1], j); } else { assertEquals(a71[1], -1); } + + if (i < e16) { assertEquals(a72[0], i); } else { assertEquals(a72[0], 0); } + if (j < e16) { assertEquals(a72[1], j); } else { assertEquals(a72[1], e16-1); } + if (i < e15) { assertEquals(a73[0], i); } else { + assertEquals(a73[0], (i < e16) ? -e15 : 0 ); } + if (j < e15) { assertEquals(a73[1], j); } else { assertEquals(a73[1], -1); } + + if (i < e8) { assertEquals(a74[0], i); } else { assertEquals(a74[0], 0); } + if (j < e8) { assertEquals(a74[1], j); } else { assertEquals(a74[1], e8-1); } + if (i < e7) { assertEquals(a75[0], i); } else { + assertEquals(a75[0], (i < e8) ? -e7 : 0); } + if (j < e7) { assertEquals(a75[1], j); } else { assertEquals(a75[1], -1); } + } +} +checkRange(); diff --git a/deps/v8/test/mjsunit/external-array.js b/deps/v8/test/mjsunit/external-array.js index 3fcd544ab6..ab5435e5d6 100644 --- a/deps/v8/test/mjsunit/external-array.js +++ b/deps/v8/test/mjsunit/external-array.js @@ -678,3 +678,37 @@ boo(built_in_array, 0, 2.5); assertEquals(2.5, goo(built_in_array, 0)); %ClearFunctionTypeFeedback(goo); %ClearFunctionTypeFeedback(boo); + +// Check all int range edge cases +function checkRange() { + var e32 = Math.pow(2,32); var e31 = Math.pow(2,31); + var e16 = Math.pow(2,16); var e15 = Math.pow(2,15); + var e8 = Math.pow(2,8); var e7 = Math.pow(2,7); + var a7 = new Uint32Array(2); var a71 = new Int32Array(2); + var a72 = new Uint16Array(2); var a73 = new Int16Array(2); + var a74 = new Uint8Array(2); var a75 = new Int8Array(2); + for (i = 1; i <= Math.pow(2,33); i *= 2) { + var j = i-1; + a7[0] = i; a71[0] = i; a72[0] = i; a73[0] = i; a74[0] = i; a75[0] = i; + a7[1] = j; a71[1] = j; a72[1] = j; a73[1] = j; a74[1] = j; a75[1] = j; + + if (i < e32) { assertEquals(a7[0], i); } else { assertEquals(a7[0], 0); } + if (j < e32) { assertEquals(a7[1], j); } else { assertEquals(a7[1],e32-1); } + if (i < e31) { assertEquals(a71[0], i); } else { + assertEquals(a71[0], (i < e32) ? -e31 : 0 ); } + if (j < e31) { assertEquals(a71[1], j); } else { assertEquals(a71[1], -1); } + + if (i < e16) { assertEquals(a72[0], i); } else { assertEquals(a72[0], 0); } + if (j < e16) { assertEquals(a72[1], j); } else { assertEquals(a72[1], e16-1); } + if (i < e15) { assertEquals(a73[0], i); } else { + assertEquals(a73[0], (i < e16) ? -e15 : 0 ); } + if (j < e15) { assertEquals(a73[1], j); } else { assertEquals(a73[1], -1); } + + if (i < e8) { assertEquals(a74[0], i); } else { assertEquals(a74[0], 0); } + if (j < e8) { assertEquals(a74[1], j); } else { assertEquals(a74[1], e8-1); } + if (i < e7) { assertEquals(a75[0], i); } else { + assertEquals(a75[0], (i < e8) ? -e7 : 0); } + if (j < e7) { assertEquals(a75[1], j); } else { assertEquals(a75[1], -1); } + } +} +checkRange(); diff --git a/deps/v8/test/mjsunit/fast-literal.js b/deps/v8/test/mjsunit/fast-literal.js new file mode 100644 index 0000000000..822d90656b --- /dev/null +++ b/deps/v8/test/mjsunit/fast-literal.js @@ -0,0 +1,42 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --no-inline-new --nouse-allocation-folding + +%SetAllocationTimeout(10, 0); +function f() { + return [[1, 2, 3], [1.1, 1.2, 1.3], [[], [], []]]; +} + +f(); f(); f(); +%OptimizeFunctionOnNextCall(f); +for (var i=0; i<1000; i++) { + f(); +} + + + diff --git a/deps/v8/test/mjsunit/fuzz-natives-part1.js b/deps/v8/test/mjsunit/fuzz-natives-part1.js index 8ca523cc6f..e76b9be6d4 100644 --- a/deps/v8/test/mjsunit/fuzz-natives-part1.js +++ b/deps/v8/test/mjsunit/fuzz-natives-part1.js @@ -150,8 +150,7 @@ var knownProblems = { "PushModuleContext": true, "LazyCompile": true, "LazyRecompile": true, - "ParallelRecompile": true, - "InstallRecompiledCode": true, + "ConcurrentRecompile": true, "NotifyDeoptimized": true, "NotifyStubFailure": true, "NotifyOSR": true, diff --git a/deps/v8/test/mjsunit/fuzz-natives-part2.js b/deps/v8/test/mjsunit/fuzz-natives-part2.js index ec84f35ada..0797deb18d 100644 --- a/deps/v8/test/mjsunit/fuzz-natives-part2.js +++ b/deps/v8/test/mjsunit/fuzz-natives-part2.js @@ -150,8 +150,7 @@ var knownProblems = { "PushModuleContext": true, "LazyCompile": true, "LazyRecompile": true, - "ParallelRecompile": true, - "InstallRecompiledCode": true, + "ConcurrentRecompile": true, "NotifyDeoptimized": true, "NotifyStubFailure": true, "NotifyOSR": true, @@ -165,6 +164,7 @@ var knownProblems = { "DeclareGlobals": true, "ArrayConstructor": true, "InternalArrayConstructor": true, + "SetAccessorProperty": true, "PromoteScheduledException": true, "DeleteHandleScopeExtensions": true, diff --git a/deps/v8/test/mjsunit/fuzz-natives-part3.js b/deps/v8/test/mjsunit/fuzz-natives-part3.js index 928fb4634f..9a3a883fe4 100644 --- a/deps/v8/test/mjsunit/fuzz-natives-part3.js +++ b/deps/v8/test/mjsunit/fuzz-natives-part3.js @@ -150,8 +150,7 @@ var knownProblems = { "PushModuleContext": true, "LazyCompile": true, "LazyRecompile": true, - "ParallelRecompile": true, - "InstallRecompiledCode": true, + "ConcurrentRecompile": true, "NotifyDeoptimized": true, "NotifyStubFailure": true, "NotifyOSR": true, diff --git a/deps/v8/test/mjsunit/fuzz-natives-part4.js b/deps/v8/test/mjsunit/fuzz-natives-part4.js index d47db3467e..83e00d2b66 100644 --- a/deps/v8/test/mjsunit/fuzz-natives-part4.js +++ b/deps/v8/test/mjsunit/fuzz-natives-part4.js @@ -150,8 +150,7 @@ var knownProblems = { "PushModuleContext": true, "LazyCompile": true, "LazyRecompile": true, - "ParallelRecompile": true, - "InstallRecompiledCode": true, + "ConcurrentRecompile": true, "NotifyDeoptimized": true, "NotifyStubFailure": true, "NotifyOSR": true, diff --git a/deps/v8/test/mjsunit/harmony/object-observe.js b/deps/v8/test/mjsunit/harmony/object-observe.js index 830eb1b09a..75f0ff8bb8 100644 --- a/deps/v8/test/mjsunit/harmony/object-observe.js +++ b/deps/v8/test/mjsunit/harmony/object-observe.js @@ -145,13 +145,8 @@ assertThrows(function() { notifier.performChange(1, function(){}); }, TypeError) assertThrows(function() { notifier.performChange(undefined, function(){}); }, TypeError); assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError); assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError); -var testSelf = {}; notifier.performChange('foo', function() { - assertTrue(testSelf === this); -}, testSelf); -var self = this; -notifier.performChange('foo', function() { - assertTrue(self === this); + assertEquals(undefined, this); }); var notify = notifier.notify; @@ -400,10 +395,11 @@ Thingy.prototype = { increment: function(amount) { var notifier = Object.getNotifier(this); + var self = this; notifier.performChange(Thingy.INCREMENT, function() { - this.a += amount; - this.b += amount; - }, this); + self.a += amount; + self.b += amount; + }); notifier.notify({ object: this, @@ -415,10 +411,11 @@ Thingy.prototype = { multiply: function(amount) { var notifier = Object.getNotifier(this); + var self = this; notifier.performChange(Thingy.MULTIPLY, function() { - this.a *= amount; - this.b *= amount; - }, this); + self.a *= amount; + self.b *= amount; + }); notifier.notify({ object: this, @@ -430,10 +427,11 @@ Thingy.prototype = { incrementAndMultiply: function(incAmount, multAmount) { var notifier = Object.getNotifier(this); + var self = this; notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() { - this.increment(incAmount); - this.multiply(multAmount); - }, this); + self.increment(incAmount); + self.multiply(multAmount); + }); notifier.notify({ object: this, @@ -505,10 +503,11 @@ RecursiveThingy.prototype = { if (!n) return; var notifier = Object.getNotifier(this); + var self = this; notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() { - this[n-1] = this[n-1]*amount; - this.multiplyFirstN(amount, n-1); - }, this); + self[n-1] = self[n-1]*amount; + self.multiplyFirstN(amount, n-1); + }); notifier.notify({ object: this, @@ -557,18 +556,19 @@ DeckSuit.prototype = { shuffle: function() { var notifier = Object.getNotifier(this); + var self = this; notifier.performChange(DeckSuit.SHUFFLE, function() { - this.reverse(); - this.sort(function() { return Math.random()* 2 - 1; }); - var cut = this.splice(0, 6); - Array.prototype.push.apply(this, cut); - this.reverse(); - this.sort(function() { return Math.random()* 2 - 1; }); - var cut = this.splice(0, 6); - Array.prototype.push.apply(this, cut); - this.reverse(); - this.sort(function() { return Math.random()* 2 - 1; }); - }, this); + self.reverse(); + self.sort(function() { return Math.random()* 2 - 1; }); + var cut = self.splice(0, 6); + Array.prototype.push.apply(self, cut); + self.reverse(); + self.sort(function() { return Math.random()* 2 - 1; }); + var cut = self.splice(0, 6); + Array.prototype.push.apply(self, cut); + self.reverse(); + self.sort(function() { return Math.random()* 2 - 1; }); + }); notifier.notify({ object: this, diff --git a/deps/v8/test/mjsunit/lithium/MulI.js b/deps/v8/test/mjsunit/lithium/MulI.js new file mode 100644 index 0000000000..68588bd512 --- /dev/null +++ b/deps/v8/test/mjsunit/lithium/MulI.js @@ -0,0 +1,70 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --no-use-osr + +function foo_smi(a, b) { + var result = a * b; + result += a * 35; + result += a * -1; + result += a * 1; + result += a * 0; + return result * a; +} + +function foo_int(a, b) { + var result = a * b; + result += a * 35; + result += a * -1; + result += a * 1; + result += a * 0; + return result * a; +} + +foo_smi(10, 5); +var r1 = foo_smi(10, 5); +%OptimizeFunctionOnNextCall(foo_smi); +var r2 = foo_smi(10, 5); + +assertEquals(r1, r2); + +foo_int(10, 21474800); +var r3 = foo_int(10, 21474800); +%OptimizeFunctionOnNextCall(foo_int); +var r4 = foo_int(10, 21474800); + +assertEquals(r3, r4); + +// Check overflow with -1 constant. +function foo2(value) { + return value * -1; +} + +foo2(-2147483600); +foo2(-2147483600); +%OptimizeFunctionOnNextCall(foo2); +assertEquals(2147483648, foo2(-2147483648)); diff --git a/deps/v8/test/mjsunit/manual-parallel-recompile.js b/deps/v8/test/mjsunit/manual-parallel-recompile.js index 84bfff1a57..0a0e61d524 100644 --- a/deps/v8/test/mjsunit/manual-parallel-recompile.js +++ b/deps/v8/test/mjsunit/manual-parallel-recompile.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --allow-natives-syntax --expose-gc -// Flags: --parallel-recompilation --parallel-recompilation-delay=50 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=50 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -53,12 +53,12 @@ f(g(1)); assertUnoptimized(f); assertUnoptimized(g); -%OptimizeFunctionOnNextCall(f, "parallel"); -%OptimizeFunctionOnNextCall(g, "parallel"); +%OptimizeFunctionOnNextCall(f, "concurrent"); +%OptimizeFunctionOnNextCall(g, "concurrent"); f(g(2)); // Trigger optimization. -assertUnoptimized(f, "no sync"); // Not yet optimized while parallel thread +assertUnoptimized(f, "no sync"); // Not yet optimized while background thread assertUnoptimized(g, "no sync"); // is running. -assertOptimized(f, "sync"); // Optimized once we sync with the parallel thread. -assertOptimized(g, "sync"); +assertOptimized(f, "sync"); // Optimized once we sync with the +assertOptimized(g, "sync"); // background thread. diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js index 83449cc1e6..129353730c 100644 --- a/deps/v8/test/mjsunit/mjsunit.js +++ b/deps/v8/test/mjsunit/mjsunit.js @@ -100,7 +100,7 @@ var assertInstanceof; var assertUnreachable; // Assert that the function code is (not) optimized. If "no sync" is passed -// as second argument, we do not wait for the parallel optimization thread to +// as second argument, we do not wait for the concurrent optimization thread to // finish when polling for optimization status. // Only works with --allow-natives-syntax. var assertOptimized; diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index 829efaf583..ee35af5a61 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -251,8 +251,5 @@ harmony/object-observe: SKIP readonly: SKIP array-feedback: SKIP -# TODO(mstarzinger): Enable once escape analysis is stabilized. -compiler/escape-analysis: SKIP - # Deopt every n garbage collections collides with the deopt every n times flag. regress/regress-2653: SKIP diff --git a/deps/v8/test/mjsunit/parallel-initial-prototype-change.js b/deps/v8/test/mjsunit/parallel-initial-prototype-change.js index 942d9abc3c..625b590fcc 100644 --- a/deps/v8/test/mjsunit/parallel-initial-prototype-change.js +++ b/deps/v8/test/mjsunit/parallel-initial-prototype-change.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --allow-natives-syntax -// Flags: --parallel-recompilation --parallel-recompilation-delay=100 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -42,7 +42,7 @@ assertEquals(0.5, f1(arr, 0)); assertEquals(0.5, f1(arr, 0)); // Optimized code of f1 depends on initial object and array maps. -%OptimizeFunctionOnNextCall(f1, "parallel"); +%OptimizeFunctionOnNextCall(f1, "concurrent"); // Trigger optimization in the background thread assertEquals(0.5, f1(arr, 0)); Object.prototype[1] = 1.5; // Invalidate current initial object map. diff --git a/deps/v8/test/mjsunit/parallel-invalidate-transition-map.js b/deps/v8/test/mjsunit/parallel-invalidate-transition-map.js index 716f63198c..9a5d31003f 100644 --- a/deps/v8/test/mjsunit/parallel-invalidate-transition-map.js +++ b/deps/v8/test/mjsunit/parallel-invalidate-transition-map.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --track-fields --track-double-fields --allow-natives-syntax -// Flags: --parallel-recompilation --parallel-recompilation-delay=100 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -46,7 +46,7 @@ function add_field(obj) { add_field(new_object()); add_field(new_object()); -%OptimizeFunctionOnNextCall(add_field, "parallel"); +%OptimizeFunctionOnNextCall(add_field, "concurrent"); var o = new_object(); // Trigger optimization in the background thread. diff --git a/deps/v8/test/mjsunit/parallel-optimize-disabled.js b/deps/v8/test/mjsunit/parallel-optimize-disabled.js index e19dbd095b..c144e649cc 100644 --- a/deps/v8/test/mjsunit/parallel-optimize-disabled.js +++ b/deps/v8/test/mjsunit/parallel-optimize-disabled.js @@ -25,11 +25,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --nodead-code-elimination --parallel-recompilation +// Flags: --nodead-code-elimination --concurrent-recompilation // Flags: --allow-natives-syntax -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -45,7 +45,7 @@ function f(x) { f(); f(); %OptimizeFunctionOnNextCall(f); -%OptimizeFunctionOnNextCall(g, "parallel"); +%OptimizeFunctionOnNextCall(g, "concurrent"); f(0); // g() is disabled for optimization on inlining attempt. // Attempt to optimize g() should not run into any assertion. assertUnoptimized(g, "sync"); diff --git a/deps/v8/test/mjsunit/regress/post-increment-close-context.js b/deps/v8/test/mjsunit/regress/post-increment-close-context.js new file mode 100644 index 0000000000..08ade10f1d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/post-increment-close-context.js @@ -0,0 +1,42 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +var foo = {bar: -2}; +function crash() { + return !(foo.bar++); +} +assertFalse(crash()); +assertEquals(-1, foo.bar); +%OptimizeFunctionOnNextCall(crash); +assertFalse(crash()); +assertEquals(0, foo.bar); +assertTrue(crash()); +assertEquals(1, foo.bar); +assertFalse(crash()); +assertEquals(2, foo.bar); diff --git a/deps/v8/test/mjsunit/regress/regress-2594.js b/deps/v8/test/mjsunit/regress/regress-2594.js new file mode 100644 index 0000000000..60720cb804 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-2594.js @@ -0,0 +1,104 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// In the assertions but the first, the ES5 spec actually requires 0, but +// that is arguably a spec bug, and other browsers return 1 like us. +// In ES6, all of those will presumably result in a ReferenceError. +// Our main concern with this test is that we do not crash, though. + +function f1() { + var XXX = 0 + try { throw 1 } catch (XXX) { + eval("var h = function() { return XXX }") + } + return h() +} +assertEquals(1, f1()) + +function f2() { + var XXX = 0 + try { throw 1 } catch (XXX) { + eval("function h(){ return XXX }") + } + return h() +} +assertEquals(1, f2()) + +function f3() { + var XXX = 0 + try { throw 1 } catch (XXX) { + try { throw 2 } catch (y) { + eval("function h(){ return XXX }") + } + } + return h() +} +assertEquals(1, f3()) + +function f4() { + var XXX = 0 + try { throw 1 } catch (XXX) { + with ({}) { + eval("function h(){ return XXX }") + } + } + return h() +} +assertEquals(1, f4()) + +function f5() { + var XXX = 0 + try { throw 1 } catch (XXX) { + eval('eval("function h(){ return XXX }")') + } + return h() +} +assertEquals(1, f5()) + +function f6() { + var XXX = 0 + try { throw 1 } catch (XXX) { + eval("var h = (function() { function g(){ return XXX } return g })()") + } + return h() +} +assertEquals(1, f6()) + +function f7() { + var XXX = 0 + try { throw 1 } catch (XXX) { + eval("function h() { var XXX=2; function g(){ return XXX } return g }") + } + return h()() +} +assertEquals(2, f7()) // ! + +var XXX = 0 +try { throw 1 } catch (XXX) { + eval("function h(){ return XXX }") +} +assertEquals(1, h()) diff --git a/deps/v8/test/mjsunit/regress/regress-2829.js b/deps/v8/test/mjsunit/regress/regress-2829.js new file mode 100644 index 0000000000..a046ae0395 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-2829.js @@ -0,0 +1,53 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --harmony-collections + +(function test1() { + var wm1 = new WeakMap(); + wm1.set(Object.prototype, 23); + assertTrue(wm1.has(Object.prototype)); + Object.freeze(Object.prototype); + + var wm2 = new WeakMap(); + var o = {}; + wm2.set(o, 42); + assertEquals(42, wm2.get(o)); +})(); + +(function test2() { + var wm1 = new WeakMap(); + var o1 = {}; + wm1.set(o1, 23); + assertTrue(wm1.has(o1)); + Object.freeze(o1); + + var wm2 = new WeakMap(); + var o2 = Object.create(o1); + wm2.set(o2, 42); + assertEquals(42, wm2.get(o2)); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-2855.js b/deps/v8/test/mjsunit/regress/regress-2855.js new file mode 100644 index 0000000000..24ec452d59 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-2855.js @@ -0,0 +1,57 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function foo(a) { + for (var i = 0; i < 100; ++i) + a = new String(a); + return a; +} + +var expected = "hello"; +for (var i = 0; i < 4; ++i) { + if (i == 2) { + String.prototype.valueOf = function() { return 42; } + expected = "42"; + } + assertEquals(expected, "" + foo("hello")); +} + +// Make sure we look up "valueOf" only once. +var count = 0; +var x = new String("foo"); +Object.defineProperty(x, "valueOf", + { get: function() { + count++; + return function() { + return 11; + } + } + }); +for (var i = 0; i < 3; i++) { + assertEquals("11", "" + x); + assertEquals(i + 1, count); +} diff --git a/deps/v8/test/mjsunit/regress/regress-convert-function-to-double.js b/deps/v8/test/mjsunit/regress/regress-convert-function-to-double.js new file mode 100644 index 0000000000..fca44f9632 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-convert-function-to-double.js @@ -0,0 +1,36 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function f(v) { + this.func = v; +} + +var o1 = new f(f); +var d = 1.4; +var o2 = new f(d); +o2.func = 1.8; +assertEquals(1.4, d) diff --git a/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js b/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js index 3a66235684..52c32e9cc3 100644 --- a/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js +++ b/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js @@ -61,8 +61,8 @@ g(); // Mark with builtin. %OptimizeFunctionOnNextCall(f); -if (%IsParallelRecompilationSupported()) { - %OptimizeFunctionOnNextCall(g, "parallel"); +if (%IsConcurrentRecompilationSupported()) { + %OptimizeFunctionOnNextCall(g, "concurrent"); } // Activate debugger. diff --git a/deps/v8/test/mjsunit/regress/regress-embedded-cons-string.js b/deps/v8/test/mjsunit/regress/regress-embedded-cons-string.js index 6a63da2fde..58a0b1c869 100644 --- a/deps/v8/test/mjsunit/regress/regress-embedded-cons-string.js +++ b/deps/v8/test/mjsunit/regress/regress-embedded-cons-string.js @@ -27,27 +27,27 @@ // Flags: --fold-constants --nodead-code-elimination // Flags: --expose-gc --allow-natives-syntax -// Flags: --parallel-recompilation --parallel-recompilation-delay=300 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=300 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } function test(fun) { fun(); fun(); - // Mark for parallel optimization. - %OptimizeFunctionOnNextCall(fun, "parallel"); + // Mark for concurrent optimization. + %OptimizeFunctionOnNextCall(fun, "concurrent"); //Trigger optimization in the background. fun(); //Tenure cons string. gc(); - // In the mean time, parallel recompiling is not complete yet. + // In the mean time, concurrent recompiling is not complete yet. assertUnoptimized(fun, "no sync"); - // Parallel recompilation eventually finishes and embeds tenured cons string. + // Concurrent recompilation eventually finishes, embeds tenured cons string. assertOptimized(fun, "sync"); - //Visit embedded cons string during mark compact. + // Visit embedded cons string during mark compact. gc(); } diff --git a/deps/v8/test/mjsunit/regress/regress-map-invalidation-2.js b/deps/v8/test/mjsunit/regress/regress-map-invalidation-2.js index 6605ba7858..1f896a495f 100644 --- a/deps/v8/test/mjsunit/regress/regress-map-invalidation-2.js +++ b/deps/v8/test/mjsunit/regress/regress-map-invalidation-2.js @@ -31,19 +31,24 @@ var c = { x: 2, y: 1 }; function g() { var outer = { foo: 1 }; - function f() { + function f(b, c) { var n = outer.foo; - for (var i = 0; i < 100000; i++) { + for (var i = 0; i < 10; i++) { n += c.x + outer.foo; } - var o2 = [{ x: 1.5, y: 1 }]; - return o2; + if (b) return [{ x: 1.5, y: 1 }]; + else return c; } + // Clear type feedback from previous stress runs. + %ClearFunctionTypeFeedback(f); return f; } var fun = g(); -fun(); +fun(false, c); +fun(false, c); +fun(false, c); +%OptimizeFunctionOnNextCall(fun); +fun(false, c); +fun(true, c); assertOptimized(fun); -fun(); - diff --git a/deps/v8/test/mjsunit/regress/regress-merge-descriptors.js b/deps/v8/test/mjsunit/regress/regress-merge-descriptors.js new file mode 100644 index 0000000000..a84a6254a0 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-merge-descriptors.js @@ -0,0 +1,92 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +var extend = function (d, b) { + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; + +var Car = (function (Super) { + var Car = function () { + var self = this; + + Super.call(self); + + Object.defineProperties(self, { + "make": { + enumerable: true, + configurable: true, + get: function () { + return "Ford"; + } + } + }); + + self.copy = function () { + throw new Error("Meant to be overriden"); + }; + + return self; + }; + + extend(Car, Super); + + return Car; +}(Object)); + + +var SuperCar = ((function (Super) { + var SuperCar = function (make) { + var self = this; + + Super.call(self); + + + Object.defineProperties(self, { + "make": { + enumerable: true, + configurable: true, + get: function () { + return make; + } + } + }); + + // Convert self.copy from CONSTANT to FIELD. + self.copy = function () { }; + + return self; + }; + extend(SuperCar, Super); + return SuperCar; +})(Car)); + +assertEquals("Ford", new Car().make); +assertEquals("Bugatti", new SuperCar("Bugatti").make); +assertEquals("Lambo", new SuperCar("Lambo").make); +assertEquals("Shelby", new SuperCar("Shelby").make); diff --git a/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js b/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js index 3de0217c81..8bf95ec5aa 100644 --- a/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js +++ b/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --allow-natives-syntax -// Flags: --parallel-recompilation --parallel-recompilation-delay=100 +// Flags: --concurrent-recompilation --concurrent-recompilation-delay=100 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -57,12 +57,12 @@ var f = function() { f(); f(); -%OptimizeFunctionOnNextCall(f, "parallel"); // Mark with builtin. -f(); // Kick off parallel recompilation. +%OptimizeFunctionOnNextCall(f, "concurrent"); // Mark with builtin. +f(); // Kick off concurrent recompilation. Debug.setListener(listener); // Activate debugger. Debug.setBreakPoint(f, 2, 0); // Force deopt. -// Sync with parallel optimization thread. But no optimized code is installed. +// Sync with optimization thread. But no optimized code is installed. assertUnoptimized(f, "sync"); f(); // Trigger break point. diff --git a/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js b/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js index e494173856..2fad5ca0d2 100644 --- a/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js +++ b/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js @@ -26,10 +26,10 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --allow-natives-syntax -// Flags: --parallel-recompilation-delay=300 +// Flags: --concurrent-recompilation-delay=300 -if (!%IsParallelRecompilationSupported()) { - print("Parallel recompilation is disabled. Skipping this test."); +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); quit(); } @@ -46,8 +46,8 @@ function bar() { } foo(); -// Mark and trigger parallel optimization. -%OptimizeFunctionOnNextCall(foo, "parallel"); +// Mark and trigger concurrent optimization. +%OptimizeFunctionOnNextCall(foo, "concurrent"); foo(); // Set break points on an unrelated function. This clears both optimized @@ -56,7 +56,7 @@ foo(); Debug.setBreakPoint(bar, 0, 0); Debug.clearAllBreakPoints(); -// Install optimized code when parallel optimization finishes. +// Install optimized code when concurrent optimization finishes. // This needs to be able to deal with shared code being a builtin. assertUnoptimized(foo, "sync"); diff --git a/deps/v8/test/mjsunit/regress/regress-store-uncacheable.js b/deps/v8/test/mjsunit/regress/regress-store-uncacheable.js new file mode 100644 index 0000000000..e9c9fc25b4 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-store-uncacheable.js @@ -0,0 +1,40 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +function f() { + var o = {}; + o["<abc>"] = 123; +} + +f(); +f(); +f(); +%OptimizeFunctionOnNextCall(f); +f(); +assertOptimized(f); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-282736.js b/deps/v8/test/mjsunit/regress/regress-x87.js index afd9f75be4..60380a8fcb 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-282736.js +++ b/deps/v8/test/mjsunit/regress/regress-x87.js @@ -25,35 +25,24 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -function funcify(obj) { - var type = typeof obj; - if (type === "object") { - var funcified = {}, foo = {}; - for (var prop in obj) { - funcified[prop] = funcify(obj[prop]); - foo[prop] = true; - } - return funcified; - } else if (type === "function") { - return obj; +// Flags: --allow-natives-syntax --noenable-sse2 + +// Regression for register allocation. +var x; +var a = new Float32Array([1,2, 4, 6, 8, 11, NaN, 1/0, -3]) +var val = 2.1*a[1]*a[0]*a[1*2*3*0]*a[1*1]*1.0; +assertEquals(8.4, val); + +// Regression for double-phis +var a; +var t = true; +var res = [2.5, 2]; +for (var i = 0; i < 2; i++) { + if (t) { + a = 1.5; } else { - return function () { return obj; }; + a = true; } + assertEquals(res[i], a+1); + t = false; } - -var obj = {}; - -obj.A = 1; -obj.B = function () { return 2; }; -obj.C = 3; -obj.D = 4; - -var funcified = funcify(obj); - -assertEquals("function", typeof funcified.A); -assertEquals(1, funcified.A()); -assertEquals("function", typeof funcified.B); -assertEquals(2, funcified.B()); -assertEquals("function", typeof funcified.C); -assertEquals("function", typeof funcified.D); -assertEquals(4, funcified.D()); diff --git a/deps/v8/test/mjsunit/smi-mul.js b/deps/v8/test/mjsunit/smi-mul.js new file mode 100644 index 0000000000..6f23d5e3a0 --- /dev/null +++ b/deps/v8/test/mjsunit/smi-mul.js @@ -0,0 +1,67 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --noalways-opt + +function mul(a, b) { + return a * b; +} + + +mul(-1, 2); +mul(-1, 2); +%OptimizeFunctionOnNextCall(mul); +assertEquals(-2, mul(-1, 2)); +assertOptimized(mul); + +// Deopt on minus zero. +assertEquals(-0, mul(-1, 0)); +assertUnoptimized(mul); + + +function mul2(a, b) { + return a * b; +} + +mul2(-1, 2); +mul2(-1, 2); +%OptimizeFunctionOnNextCall(mul2); + +// 2^30 is a smi boundary on arm and ia32. +var two_30 = 1 << 30; +// 2^31 is a smi boundary on x64. +var two_31 = 2 * two_30; + +if (%IsValidSmi(two_31)) { + // Deopt on two_31 on x64. + assertEquals(two_31, mul2(-two_31, -1)); + assertUnoptimized(mul2); +} else { + // Deopt on two_30 on ia32. + assertEquals(two_30, mul2(-two_30, -1)); + assertUnoptimized(mul2); +} diff --git a/deps/v8/test/mjsunit/track-fields.js b/deps/v8/test/mjsunit/track-fields.js index 8b0ec29623..4da1ab5d22 100644 --- a/deps/v8/test/mjsunit/track-fields.js +++ b/deps/v8/test/mjsunit/track-fields.js @@ -211,7 +211,6 @@ assertFalse(%HaveSameMap(o18, o19)); delete o18.to_delete; delete o19.to_delete; -assertTrue(%HaveSameMap(o18, o19)); assertEquals(1, o18.field2); assertEquals(1.6, o19.field2); |