| Index: test/cctest/test-api.cc
|
| diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
| old mode 100755
|
| new mode 100644
|
| index b95f292b6e1c1763e1eefd64086ed7ebcbc8fe6d..f8f1930285663cc05eabec606733c29b40de2b9b
|
| --- a/test/cctest/test-api.cc
|
| +++ b/test/cctest/test-api.cc
|
| @@ -31,21 +31,24 @@
|
| #include <signal.h> // kill
|
| #include <unistd.h> // getpid
|
| #endif // WIN32
|
| +#include <string>
|
| +#include <map>
|
|
|
| #include "v8.h"
|
|
|
| #include "api.h"
|
| #include "arguments.h"
|
| -#include "isolate.h"
|
| +#include "cctest.h"
|
| #include "compilation-cache.h"
|
| +#include "cpu-profiler.h"
|
| #include "execution.h"
|
| +#include "isolate.h"
|
| #include "objects.h"
|
| -#include "snapshot.h"
|
| -#include "platform.h"
|
| -#include "utils.h"
|
| -#include "cctest.h"
|
| #include "parser.h"
|
| +#include "platform.h"
|
| +#include "snapshot.h"
|
| #include "unicode-inl.h"
|
| +#include "utils.h"
|
|
|
| static const bool kLogThreading = false;
|
|
|
| @@ -99,12 +102,14 @@ static void ExpectString(const char* code, const char* expected) {
|
| CHECK_EQ(expected, *utf8);
|
| }
|
|
|
| +
|
| static void ExpectInt32(const char* code, int expected) {
|
| Local<Value> result = CompileRun(code);
|
| CHECK(result->IsInt32());
|
| CHECK_EQ(expected, result->Int32Value());
|
| }
|
|
|
| +
|
| static void ExpectBoolean(const char* code, bool expected) {
|
| Local<Value> result = CompileRun(code);
|
| CHECK(result->IsBoolean());
|
| @@ -857,10 +862,12 @@ static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
|
| info.GetReturnValue().Set(v8_num(102));
|
| }
|
|
|
| +
|
| static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
|
| return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
|
| }
|
|
|
| +
|
| static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
|
| return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
|
| }
|
| @@ -1074,6 +1081,7 @@ Handle<Value> TestFastReturnValues() {
|
| return scope.Close(CompileRun("callback_object.callback()"));
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(FastReturnValues) {
|
| LocalContext env;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -1690,6 +1698,7 @@ static void EchoNamedProperty(Local<String> name,
|
| info.GetReturnValue().Set(name);
|
| }
|
|
|
| +
|
| // Helper functions for Interceptor/Accessor interaction tests
|
|
|
| void SimpleAccessorGetter(Local<String> name,
|
| @@ -1752,6 +1761,7 @@ void AddInterceptor(Handle<FunctionTemplate> templ,
|
| templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
|
| }
|
|
|
| +
|
| THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1769,6 +1779,7 @@ THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
|
| ExpectInt32("child.accessor_age", 10);
|
| }
|
|
|
| +
|
| THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1789,6 +1800,7 @@ THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
|
| ExpectInt32("child.accessor_age", 10);
|
| }
|
|
|
| +
|
| THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1808,6 +1820,7 @@ THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
|
| ExpectString("parent.name", "Alice");
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromInterceptorToAccessor) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| @@ -1825,6 +1838,7 @@ THREADED_TEST(SwitchFromInterceptorToAccessor) {
|
| ExpectInt32("obj.accessor_age", 10000);
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromAccessorToInterceptor) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| @@ -1842,6 +1856,7 @@ THREADED_TEST(SwitchFromAccessorToInterceptor) {
|
| ExpectInt32("obj.interceptor_age", 9999);
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1861,6 +1876,7 @@ THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
|
| ExpectInt32("child.accessor_age", 10000);
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1880,6 +1896,7 @@ THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
|
| ExpectInt32("child.interceptor_age", 9999);
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| @@ -1904,6 +1921,7 @@ THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
|
| ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> templ = FunctionTemplate::New();
|
| @@ -1928,6 +1946,7 @@ THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
|
| ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromInterceptorToProperty) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1945,6 +1964,7 @@ THREADED_TEST(SwitchFromInterceptorToProperty) {
|
| ExpectInt32("child.age", 10000);
|
| }
|
|
|
| +
|
| THREADED_TEST(SwitchFromPropertyToInterceptor) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| @@ -1962,6 +1982,7 @@ THREADED_TEST(SwitchFromPropertyToInterceptor) {
|
| ExpectInt32("child.interceptor_age", 9999);
|
| }
|
|
|
| +
|
| THREADED_TEST(NamedPropertyHandlerGetter) {
|
| echo_named_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -2401,6 +2422,7 @@ static void CheckEmbedderData(LocalContext* env,
|
| CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
|
| }
|
|
|
| +
|
| THREADED_TEST(EmbedderData) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| @@ -2550,6 +2572,14 @@ class ScopedArrayBufferContents {
|
| const v8::ArrayBuffer::Contents contents_;
|
| };
|
|
|
| +template <typename T>
|
| +static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
|
| + CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
|
| + for (int i = 0; i < value->InternalFieldCount(); i++) {
|
| + CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
|
| + }
|
| +}
|
| +
|
|
|
| THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
|
| i::FLAG_harmony_array_buffer = true;
|
| @@ -2560,6 +2590,7 @@ THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
|
| v8::HandleScope handle_scope(isolate);
|
|
|
| Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024);
|
| + CheckInternalFieldsAreZero(ab);
|
| CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
|
| CHECK(!ab->IsExternal());
|
| HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| @@ -2604,6 +2635,7 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
|
| "u8_a[0] = 0xAA;"
|
| "u8_a[1] = 0xFF; u8_a.buffer");
|
| Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
|
| + CheckInternalFieldsAreZero(ab1);
|
| CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
|
| CHECK(!ab1->IsExternal());
|
| ScopedArrayBufferContents ab1_contents(ab1->Externalize());
|
| @@ -2644,6 +2676,7 @@ THREADED_TEST(ArrayBuffer_External) {
|
| i::ScopedVector<uint8_t> my_data(100);
|
| memset(my_data.start(), 0, 100);
|
| Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100);
|
| + CheckInternalFieldsAreZero(ab3);
|
| CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
|
| CHECK(ab3->IsExternal());
|
|
|
| @@ -2696,6 +2729,7 @@ static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
|
| int byteOffset,
|
| int length) {
|
| v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
|
| + CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
|
| CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
|
| CHECK_EQ(length, static_cast<int>(ta->Length()));
|
| CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
|
| @@ -2733,6 +2767,7 @@ THREADED_TEST(ArrayBuffer_NeuteringApi) {
|
| CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
|
|
|
| v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
|
| + CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
|
| CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
|
| CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
|
|
|
| @@ -2751,6 +2786,7 @@ THREADED_TEST(ArrayBuffer_NeuteringApi) {
|
| CheckDataViewIsNeutered(dv);
|
| }
|
|
|
| +
|
| THREADED_TEST(ArrayBuffer_NeuteringScript) {
|
| LocalContext env;
|
| v8::Isolate* isolate = env->GetIsolate();
|
| @@ -3712,7 +3748,7 @@ TEST(OutOfMemory) {
|
| static const int K = 1024;
|
| v8::ResourceConstraints constraints;
|
| constraints.set_max_young_space_size(256 * K);
|
| - constraints.set_max_old_space_size(4 * K * K);
|
| + constraints.set_max_old_space_size(5 * K * K);
|
| v8::SetResourceConstraints(&constraints);
|
|
|
| // Execute a script that causes out of memory.
|
| @@ -3753,7 +3789,7 @@ TEST(OutOfMemoryNested) {
|
| static const int K = 1024;
|
| v8::ResourceConstraints constraints;
|
| constraints.set_max_young_space_size(256 * K);
|
| - constraints.set_max_old_space_size(4 * K * K);
|
| + constraints.set_max_old_space_size(5 * K * K);
|
| v8::SetResourceConstraints(&constraints);
|
|
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -3782,7 +3818,7 @@ TEST(HugeConsStringOutOfMemory) {
|
| static const int K = 1024;
|
| v8::ResourceConstraints constraints;
|
| constraints.set_max_young_space_size(256 * K);
|
| - constraints.set_max_old_space_size(3 * K * K);
|
| + constraints.set_max_old_space_size(4 * K * K);
|
| v8::SetResourceConstraints(&constraints);
|
|
|
| // Execute a script that causes out of memory.
|
| @@ -4383,6 +4419,7 @@ TEST(ExceptionOrder) {
|
| fun->Call(fun, argc, a5);
|
| }
|
|
|
| +
|
| void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| ApiTestFuzzer::Fuzz();
|
| CHECK_EQ(1, args.Length());
|
| @@ -4500,6 +4537,47 @@ TEST(TryCatchNested) {
|
| }
|
|
|
|
|
| +void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
|
| + CHECK(try_catch->HasCaught());
|
| + Handle<Message> message = try_catch->Message();
|
| + Handle<Value> resource = message->GetScriptResourceName();
|
| + CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
|
| + CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
|
| + "Uncaught Error: a"));
|
| + CHECK_EQ(1, message->GetLineNumber());
|
| + CHECK_EQ(6, message->GetStartColumn());
|
| +}
|
| +
|
| +
|
| +void TryCatchMixedNestingHelper(
|
| + const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| + ApiTestFuzzer::Fuzz();
|
| + v8::TryCatch try_catch;
|
| + CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
|
| + CHECK(try_catch.HasCaught());
|
| + TryCatchMixedNestingCheck(&try_catch);
|
| + try_catch.ReThrow();
|
| +}
|
| +
|
| +
|
| +// This test ensures that an outer TryCatch in the following situation:
|
| +// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
|
| +// does not clobber the Message object generated for the inner TryCatch.
|
| +// This exercises the ability of TryCatch.ReThrow() to restore the
|
| +// inner pending Message before throwing the exception again.
|
| +TEST(TryCatchMixedNesting) {
|
| + v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| + v8::V8::Initialize();
|
| + v8::TryCatch try_catch;
|
| + Local<ObjectTemplate> templ = ObjectTemplate::New();
|
| + templ->Set(v8_str("TryCatchMixedNestingHelper"),
|
| + v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
|
| + LocalContext context(0, templ);
|
| + CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
|
| + TryCatchMixedNestingCheck(&try_catch);
|
| +}
|
| +
|
| +
|
| THREADED_TEST(Equality) {
|
| LocalContext context;
|
| v8::Isolate* isolate = context->GetIsolate();
|
| @@ -4564,6 +4642,7 @@ THREADED_TEST(SimplePropertyRead) {
|
| }
|
| }
|
|
|
| +
|
| THREADED_TEST(DefinePropertyOnAPIAccessor) {
|
| LocalContext context;
|
| v8::HandleScope scope(context->GetIsolate());
|
| @@ -4611,6 +4690,7 @@ THREADED_TEST(DefinePropertyOnAPIAccessor) {
|
| CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
|
| }
|
|
|
| +
|
| THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| Local<ObjectTemplate> templ = ObjectTemplate::New();
|
| @@ -6274,6 +6354,7 @@ void WhammyPropertyGetter(Local<String> name,
|
| info.GetReturnValue().Set(whammy->getScript()->Run());
|
| }
|
|
|
| +
|
| THREADED_TEST(WeakReference) {
|
| v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
|
| @@ -7409,6 +7490,7 @@ static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
|
| CHECK_EQ(" new o.foo();", *source_line);
|
| }
|
|
|
| +
|
| TEST(ExceptionInNativeScript) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| @@ -10669,6 +10751,7 @@ static void FastApiCallback_SimpleSignature(
|
| args.GetReturnValue().Set(args[0]->Int32Value() + 1);
|
| }
|
|
|
| +
|
| // Helper to maximize the odds of object moving.
|
| static void GenerateSomeGarbage() {
|
| CompileRun(
|
| @@ -10770,6 +10853,7 @@ static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
|
| CHECK_EQ(31, p_getter_count);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
|
| LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
|
| }
|
| @@ -10825,6 +10909,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
|
| CHECK_EQ(100, interceptor_call_count);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
|
| int interceptor_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -10856,6 +10941,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
|
| CHECK_EQ(100, interceptor_call_count);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
|
| int interceptor_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -10893,6 +10979,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
|
| CHECK_GE(interceptor_call_count, 50);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
|
| int interceptor_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -10930,6 +11017,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
|
| CHECK_GE(interceptor_call_count, 50);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
|
| int interceptor_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -10970,6 +11058,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
|
| CHECK_GE(interceptor_call_count, 50);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
|
| int interceptor_call_count = 0;
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -11010,6 +11099,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
|
| CHECK_GE(interceptor_call_count, 50);
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
| @@ -11034,6 +11124,7 @@ THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
|
| CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
| @@ -11062,6 +11153,7 @@ THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
|
| CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
| @@ -11095,6 +11187,7 @@ THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
|
| CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
| @@ -11131,6 +11224,7 @@ THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
|
| CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
|
| }
|
|
|
| +
|
| THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
| @@ -11281,6 +11375,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
|
| CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
|
| }
|
|
|
| +
|
| // Test the map transition before the interceptor.
|
| THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -11383,6 +11478,7 @@ static void InterceptorICExceptionGetter(
|
| }
|
| }
|
|
|
| +
|
| // Test interceptor load/call IC where the interceptor throws an
|
| // exception once in a while.
|
| THREADED_TEST(InterceptorICGetterExceptions) {
|
| @@ -11426,6 +11522,7 @@ static void InterceptorICExceptionSetter(
|
| }
|
| }
|
|
|
| +
|
| // Test interceptor store IC where the interceptor throws an exception
|
| // once in a while.
|
| THREADED_TEST(InterceptorICSetterExceptions) {
|
| @@ -11589,6 +11686,7 @@ static void WebKitLike(Handle<Message> message, Handle<Value> data) {
|
| message->GetScriptResourceName();
|
| }
|
|
|
| +
|
| THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
|
| LocalContext context;
|
| HandleScope scope(context->GetIsolate());
|
| @@ -11907,24 +12005,28 @@ TEST(Threading1) {
|
| ApiTestFuzzer::TearDown();
|
| }
|
|
|
| +
|
| TEST(Threading2) {
|
| ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
|
| ApiTestFuzzer::RunAllTests();
|
| ApiTestFuzzer::TearDown();
|
| }
|
|
|
| +
|
| TEST(Threading3) {
|
| ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
|
| ApiTestFuzzer::RunAllTests();
|
| ApiTestFuzzer::TearDown();
|
| }
|
|
|
| +
|
| TEST(Threading4) {
|
| ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
|
| ApiTestFuzzer::RunAllTests();
|
| ApiTestFuzzer::TearDown();
|
| }
|
|
|
| +
|
| void ApiTestFuzzer::CallTest() {
|
| if (kLogThreading)
|
| printf("Start test %d\n", test_number_);
|
| @@ -12263,68 +12365,268 @@ THREADED_TEST(NestedHandleScopeAndContexts) {
|
| }
|
|
|
|
|
| -static i::Handle<i::JSFunction>* foo_ptr = NULL;
|
| -static int foo_entry_count = 0;
|
| -static i::Handle<i::JSFunction>* bar_ptr = NULL;
|
| -static int bar_entry_count = 0;
|
| -static int bar_caller_count = 0;
|
| +static bool MatchPointers(void* key1, void* key2) {
|
| + return key1 == key2;
|
| +}
|
| +
|
| +
|
| +struct SymbolInfo {
|
| + size_t id;
|
| + size_t size;
|
| + std::string name;
|
| +};
|
| +
|
| +
|
| +class SetFunctionEntryHookTest {
|
| + public:
|
| + SetFunctionEntryHookTest() {
|
| + CHECK(instance_ == NULL);
|
| + instance_ = this;
|
| + }
|
| + ~SetFunctionEntryHookTest() {
|
| + CHECK(instance_ == this);
|
| + instance_ = NULL;
|
| + }
|
| + void Reset() {
|
| + symbols_.clear();
|
| + symbol_locations_.clear();
|
| + invocations_.clear();
|
| + }
|
| + void RunTest();
|
| + void OnJitEvent(const v8::JitCodeEvent* event);
|
| + static void JitEvent(const v8::JitCodeEvent* event) {
|
| + CHECK(instance_ != NULL);
|
| + instance_->OnJitEvent(event);
|
| + }
|
| +
|
| + void OnEntryHook(uintptr_t function,
|
| + uintptr_t return_addr_location);
|
| + static void EntryHook(uintptr_t function,
|
| + uintptr_t return_addr_location) {
|
| + CHECK(instance_ != NULL);
|
| + instance_->OnEntryHook(function, return_addr_location);
|
| + }
|
| +
|
| + static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| + CHECK(instance_ != NULL);
|
| + args.GetReturnValue().Set(v8_num(42));
|
| + }
|
| + void RunLoopInNewEnv(v8::Isolate* isolate);
|
| +
|
| + // Records addr as location of symbol.
|
| + void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
|
| +
|
| + // Finds the symbol containing addr
|
| + SymbolInfo* FindSymbolForAddr(i::Address addr);
|
| + // Returns the number of invocations where the caller name contains
|
| + // \p caller_name and the function name contains \p function_name.
|
| + int CountInvocations(const char* caller_name,
|
| + const char* function_name);
|
| +
|
| + i::Handle<i::JSFunction> foo_func_;
|
| + i::Handle<i::JSFunction> bar_func_;
|
| +
|
| + typedef std::map<size_t, SymbolInfo> SymbolMap;
|
| + typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
|
| + typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
|
| + SymbolMap symbols_;
|
| + SymbolLocationMap symbol_locations_;
|
| + InvocationMap invocations_;
|
| +
|
| + static SetFunctionEntryHookTest* instance_;
|
| +};
|
| +SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
|
| +
|
| +
|
| +// Returns true if addr is in the range [start, start+len).
|
| +static bool Overlaps(i::Address start, size_t len, i::Address addr) {
|
| + if (start <= addr && start + len > addr)
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
|
| + SymbolInfo* symbol) {
|
| + // Insert the symbol at the new location.
|
| + SymbolLocationMap::iterator it =
|
| + symbol_locations_.insert(std::make_pair(addr, symbol)).first;
|
| + // Now erase symbols to the left and right that overlap this one.
|
| + while (it != symbol_locations_.begin()) {
|
| + SymbolLocationMap::iterator left = it;
|
| + --left;
|
| + if (!Overlaps(left->first, left->second->size, addr))
|
| + break;
|
| + symbol_locations_.erase(left);
|
| + }
|
| +
|
| + // Now erase symbols to the left and right that overlap this one.
|
| + while (true) {
|
| + SymbolLocationMap::iterator right = it;
|
| + ++right;
|
| + if (right == symbol_locations_.end())
|
| + break;
|
| + if (!Overlaps(addr, symbol->size, right->first))
|
| + break;
|
| + symbol_locations_.erase(right);
|
| + }
|
| +}
|
| +
|
| +
|
| +void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
|
| + switch (event->type) {
|
| + case v8::JitCodeEvent::CODE_ADDED: {
|
| + CHECK(event->code_start != NULL);
|
| + CHECK_NE(0, static_cast<int>(event->code_len));
|
| + CHECK(event->name.str != NULL);
|
| + size_t symbol_id = symbols_.size();
|
| +
|
| + // Record the new symbol.
|
| + SymbolInfo& info = symbols_[symbol_id];
|
| + info.id = symbol_id;
|
| + info.size = event->code_len;
|
| + info.name.assign(event->name.str, event->name.str + event->name.len);
|
|
|
| + // And record it's location.
|
| + InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
|
| + }
|
| + break;
|
| +
|
| + case v8::JitCodeEvent::CODE_MOVED: {
|
| + // We would like to never see code move that we haven't seen before,
|
| + // but the code creation event does not happen until the line endings
|
| + // have been calculated (this is so that we can report the line in the
|
| + // script at which the function source is found, see
|
| + // Compiler::RecordFunctionCompilation) and the line endings
|
| + // calculations can cause a GC, which can move the newly created code
|
| + // before its existence can be logged.
|
| + SymbolLocationMap::iterator it(
|
| + symbol_locations_.find(
|
| + reinterpret_cast<i::Address>(event->code_start)));
|
| + if (it != symbol_locations_.end()) {
|
| + // Found a symbol at this location, move it.
|
| + SymbolInfo* info = it->second;
|
| + symbol_locations_.erase(it);
|
| + InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
|
| + info);
|
| + }
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +}
|
|
|
| -static void entry_hook(uintptr_t function,
|
| - uintptr_t return_addr_location) {
|
| - i::Code* code = i::Code::GetCodeFromTargetAddress(
|
| +void SetFunctionEntryHookTest::OnEntryHook(
|
| + uintptr_t function, uintptr_t return_addr_location) {
|
| + // Get the function's code object.
|
| + i::Code* function_code = i::Code::GetCodeFromTargetAddress(
|
| reinterpret_cast<i::Address>(function));
|
| - CHECK(code != NULL);
|
| + CHECK(function_code != NULL);
|
|
|
| - if (bar_ptr != NULL && code == (*bar_ptr)->code())
|
| - ++bar_entry_count;
|
| + // Then try and look up the caller's code object.
|
| + i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
|
|
|
| - if (foo_ptr != NULL && code == (*foo_ptr)->code())
|
| - ++foo_entry_count;
|
| + // Count the invocation.
|
| + SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
|
| + SymbolInfo* function_symbol =
|
| + FindSymbolForAddr(reinterpret_cast<i::Address>(function));
|
| + ++invocations_[std::make_pair(caller_symbol, function_symbol)];
|
|
|
| - // Let's check whether bar is the caller.
|
| - if (bar_ptr != NULL) {
|
| - const v8::internal::byte* caller =
|
| - *reinterpret_cast<v8::internal::byte**>(return_addr_location);
|
| + if (!bar_func_.is_null() && function_code == bar_func_->code()) {
|
| + // Check that we have a symbol for the "bar" function at the right location.
|
| + SymbolLocationMap::iterator it(
|
| + symbol_locations_.find(function_code->instruction_start()));
|
| + CHECK(it != symbol_locations_.end());
|
| + }
|
|
|
| - if ((*bar_ptr)->code()->instruction_start() <= caller &&
|
| - (*bar_ptr)->code()->instruction_end() > caller) {
|
| - ++bar_caller_count;
|
| - }
|
| + if (!foo_func_.is_null() && function_code == foo_func_->code()) {
|
| + // Check that we have a symbol for "foo" at the right location.
|
| + SymbolLocationMap::iterator it(
|
| + symbol_locations_.find(function_code->instruction_start()));
|
| + CHECK(it != symbol_locations_.end());
|
| }
|
| }
|
|
|
|
|
| -static void RunLoopInNewEnv() {
|
| - bar_ptr = NULL;
|
| - foo_ptr = NULL;
|
| +SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
|
| + SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
|
| + // Do we have a direct hit on a symbol?
|
| + if (it != symbol_locations_.end()) {
|
| + if (it->first == addr)
|
| + return it->second;
|
| + }
|
|
|
| - v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| + // If not a direct hit, it'll have to be the previous symbol.
|
| + if (it == symbol_locations_.begin())
|
| + return NULL;
|
| +
|
| + --it;
|
| + size_t offs = addr - it->first;
|
| + if (offs < it->second->size)
|
| + return it->second;
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +int SetFunctionEntryHookTest::CountInvocations(
|
| + const char* caller_name, const char* function_name) {
|
| + InvocationMap::iterator it(invocations_.begin());
|
| + int invocations = 0;
|
| + for (; it != invocations_.end(); ++it) {
|
| + SymbolInfo* caller = it->first.first;
|
| + SymbolInfo* function = it->first.second;
|
| +
|
| + // Filter out non-matching functions.
|
| + if (function_name != NULL) {
|
| + if (function->name.find(function_name) == std::string::npos)
|
| + continue;
|
| + }
|
| +
|
| + // Filter out non-matching callers.
|
| + if (caller_name != NULL) {
|
| + if (caller == NULL)
|
| + continue;
|
| + if (caller->name.find(caller_name) == std::string::npos)
|
| + continue;
|
| + }
|
| +
|
| + // It matches add the invocation count to the tally.
|
| + invocations += it->second;
|
| + }
|
| +
|
| + return invocations;
|
| +}
|
| +
|
| +
|
| +void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
|
| v8::HandleScope outer(isolate);
|
| v8::Local<Context> env = Context::New(isolate);
|
| env->Enter();
|
|
|
| + Local<ObjectTemplate> t = ObjectTemplate::New();
|
| + t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback));
|
| + env->Global()->Set(v8_str("obj"), t->NewInstance());
|
| +
|
| const char* script =
|
| - "function bar() {"
|
| - " var sum = 0;"
|
| - " for (i = 0; i < 100; ++i)"
|
| - " sum = foo(i);"
|
| - " return sum;"
|
| - "}"
|
| - "function foo(i) { return i * i; }";
|
| + "function bar() {\n"
|
| + " var sum = 0;\n"
|
| + " for (i = 0; i < 100; ++i)\n"
|
| + " sum = foo(i);\n"
|
| + " return sum;\n"
|
| + "}\n"
|
| + "function foo(i) { return i * i; }\n"
|
| + "// Invoke on the runtime function.\n"
|
| + "obj.asdf()";
|
| CompileRun(script);
|
| - i::Handle<i::JSFunction> bar =
|
| - i::Handle<i::JSFunction>::cast(
|
| + bar_func_ = i::Handle<i::JSFunction>::cast(
|
| v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
|
| - ASSERT(*bar);
|
| + ASSERT(!bar_func_.is_null());
|
|
|
| - i::Handle<i::JSFunction> foo =
|
| + foo_func_ =
|
| i::Handle<i::JSFunction>::cast(
|
| v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
|
| - ASSERT(*foo);
|
| -
|
| - bar_ptr = &bar;
|
| - foo_ptr = &foo;
|
| + ASSERT(!foo_func_.is_null());
|
|
|
| v8::Handle<v8::Value> value = CompileRun("bar();");
|
| CHECK(value->IsNumber());
|
| @@ -12340,6 +12642,56 @@ static void RunLoopInNewEnv() {
|
| }
|
|
|
|
|
| +void SetFunctionEntryHookTest::RunTest() {
|
| + // Work in a new isolate throughout.
|
| + v8::Isolate* isolate = v8::Isolate::New();
|
| +
|
| + // Test setting the entry hook on the new isolate.
|
| + CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
|
| +
|
| + // Replacing the hook, once set should fail.
|
| + CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
|
| +
|
| + {
|
| + v8::Isolate::Scope scope(isolate);
|
| +
|
| + v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
|
| +
|
| + RunLoopInNewEnv(isolate);
|
| +
|
| + // Check the exepected invocation counts.
|
| + CHECK_EQ(2, CountInvocations(NULL, "bar"));
|
| + CHECK_EQ(200, CountInvocations("bar", "foo"));
|
| + CHECK_EQ(200, CountInvocations(NULL, "foo"));
|
| +
|
| + // Verify that we have an entry hook on some specific stubs.
|
| + CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
|
| + CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
|
| + CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
|
| + }
|
| + isolate->Dispose();
|
| +
|
| + Reset();
|
| +
|
| + // Make sure a second isolate is unaffected by the previous entry hook.
|
| + isolate = v8::Isolate::New();
|
| + {
|
| + v8::Isolate::Scope scope(isolate);
|
| +
|
| + // Reset the entry count to zero and set the entry hook.
|
| + RunLoopInNewEnv(isolate);
|
| +
|
| + // We should record no invocations in this isolate.
|
| + CHECK_EQ(0, static_cast<int>(invocations_.size()));
|
| + }
|
| + // Since the isolate has been used, we shouldn't be able to set an entry
|
| + // hook anymore.
|
| + CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
|
| +
|
| + isolate->Dispose();
|
| +}
|
| +
|
| +
|
| TEST(SetFunctionEntryHook) {
|
| // FunctionEntryHook does not work well with experimental natives.
|
| // Experimental natives are compiled during snapshot deserialization.
|
| @@ -12351,42 +12703,8 @@ TEST(SetFunctionEntryHook) {
|
| i::FLAG_allow_natives_syntax = true;
|
| i::FLAG_use_inlining = false;
|
|
|
| - // Test setting and resetting the entry hook.
|
| - // Nulling it should always succeed.
|
| - CHECK(v8::V8::SetFunctionEntryHook(NULL));
|
| -
|
| - CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
|
| - // Setting a hook while one's active should fail.
|
| - CHECK_EQ(false, v8::V8::SetFunctionEntryHook(entry_hook));
|
| -
|
| - CHECK(v8::V8::SetFunctionEntryHook(NULL));
|
| -
|
| - // Reset the entry count to zero and set the entry hook.
|
| - bar_entry_count = 0;
|
| - bar_caller_count = 0;
|
| - foo_entry_count = 0;
|
| - CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
|
| - RunLoopInNewEnv();
|
| -
|
| - CHECK_EQ(2, bar_entry_count);
|
| - CHECK_EQ(200, bar_caller_count);
|
| - CHECK_EQ(200, foo_entry_count);
|
| -
|
| - // Clear the entry hook and count.
|
| - bar_entry_count = 0;
|
| - bar_caller_count = 0;
|
| - foo_entry_count = 0;
|
| - v8::V8::SetFunctionEntryHook(NULL);
|
| -
|
| - // Clear the compilation cache to make sure we don't reuse the
|
| - // functions from the previous invocation.
|
| - v8::internal::Isolate::Current()->compilation_cache()->Clear();
|
| -
|
| - // Verify that entry hooking is now disabled.
|
| - RunLoopInNewEnv();
|
| - CHECK_EQ(0u, bar_entry_count);
|
| - CHECK_EQ(0u, bar_caller_count);
|
| - CHECK_EQ(0u, foo_entry_count);
|
| + SetFunctionEntryHookTest test;
|
| + test.RunTest();
|
| }
|
|
|
|
|
| @@ -12412,13 +12730,18 @@ static bool FunctionNameIs(const char* expected,
|
| const char* tail = event->name.str + kPreambleLen;
|
| size_t tail_len = event->name.len - kPreambleLen;
|
| size_t expected_len = strlen(expected);
|
| - if (tail_len == expected_len + 1) {
|
| - if (*tail == '*' || *tail == '~') {
|
| - --tail_len;
|
| - ++tail;
|
| - } else {
|
| - return false;
|
| - }
|
| + if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
|
| + --tail_len;
|
| + ++tail;
|
| + }
|
| +
|
| + // Check for tails like 'bar :1'.
|
| + if (tail_len > expected_len + 2 &&
|
| + tail[expected_len] == ' ' &&
|
| + tail[expected_len + 1] == ':' &&
|
| + tail[expected_len + 2] &&
|
| + !strncmp(tail, expected, expected_len)) {
|
| + return true;
|
| }
|
|
|
| if (tail_len != expected_len)
|
| @@ -12528,11 +12851,6 @@ static void event_handler(const v8::JitCodeEvent* event) {
|
| }
|
|
|
|
|
| -static bool MatchPointers(void* key1, void* key2) {
|
| - return key1 == key2;
|
| -}
|
| -
|
| -
|
| TEST(SetJitCodeEventHandler) {
|
| i::FLAG_stress_compaction = true;
|
| i::FLAG_incremental_marking = false;
|
| @@ -12872,6 +13190,7 @@ THREADED_TEST(PropertyEnumeration) {
|
| CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
|
| }
|
|
|
| +
|
| THREADED_TEST(PropertyEnumeration2) {
|
| LocalContext context;
|
| v8::HandleScope scope(context->GetIsolate());
|
| @@ -13980,6 +14299,7 @@ static void ForceSetInterceptSetter(
|
| info.GetReturnValue().SetUndefined();
|
| }
|
|
|
| +
|
| TEST(ForceSet) {
|
| force_set_get_count = 0;
|
| force_set_set_count = 0;
|
| @@ -14021,6 +14341,7 @@ TEST(ForceSet) {
|
| CHECK_EQ(2, force_set_get_count);
|
| }
|
|
|
| +
|
| TEST(ForceSetWithInterceptor) {
|
| force_set_get_count = 0;
|
| force_set_set_count = 0;
|
| @@ -15480,6 +15801,7 @@ void TypedArrayTestHelper(v8::ExternalArrayType array_type,
|
| backing_store.start(), (kElementCount+2)*sizeof(ElementType));
|
| Local<TypedArray> ta =
|
| TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
|
| + CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
|
| CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
|
| CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
|
| CHECK_EQ(kElementCount*sizeof(ElementType),
|
| @@ -15565,6 +15887,7 @@ THREADED_TEST(DataView) {
|
| backing_store.start(), 2 + kSize);
|
| Local<v8::DataView> dv =
|
| v8::DataView::New(ab, 2, kSize);
|
| + CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
|
| CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
|
| CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
|
| CHECK_EQ(ab, dv->Buffer());
|
| @@ -15584,6 +15907,7 @@ THREADED_TEST(DataView) {
|
| "new " #View "(ab)"); \
|
| CHECK(result->IsArrayBufferView()); \
|
| CHECK(result->Is##View()); \
|
| + CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
|
| }
|
|
|
| IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
|
| @@ -15765,6 +16089,7 @@ static void StackTraceForUncaughtExceptionListener(
|
| stack_trace->GetFrame(1));
|
| }
|
|
|
| +
|
| TEST(CaptureStackTraceForUncaughtException) {
|
| report_count = 0;
|
| LocalContext env;
|
| @@ -16072,6 +16397,7 @@ TEST(DynamicWithSourceURLInStackTrace) {
|
| CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
|
| }
|
|
|
| +
|
| static void CreateGarbageInOldSpace() {
|
| i::Factory* factory = i::Isolate::Current()->factory();
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| @@ -16081,6 +16407,7 @@ static void CreateGarbageInOldSpace() {
|
| }
|
| }
|
|
|
| +
|
| // Test that idle notification can be handled and eventually returns true.
|
| TEST(IdleNotification) {
|
| const intptr_t MB = 1024 * 1024;
|
| @@ -16298,6 +16625,7 @@ class VisitorImpl : public v8::ExternalResourceVisitor {
|
| bool found_resource_[4];
|
| };
|
|
|
| +
|
| TEST(VisitExternalStrings) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| @@ -16357,6 +16685,7 @@ static double DoubleToDateTime(double input) {
|
| return (input < 0) ? -(floor(-input)) : floor(input);
|
| }
|
|
|
| +
|
| // We don't have a consistent way to write 64-bit constants syntactically, so we
|
| // split them into two 32-bit constants and combine them programmatically.
|
| static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
|
| @@ -16596,6 +16925,7 @@ THREADED_TEST(ScriptOrigin) {
|
| CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
|
| }
|
|
|
| +
|
| THREADED_TEST(FunctionGetInferredName) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| @@ -16608,6 +16938,7 @@ THREADED_TEST(FunctionGetInferredName) {
|
| CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
|
| }
|
|
|
| +
|
| THREADED_TEST(ScriptLineNumber) {
|
| LocalContext env;
|
| v8::HandleScope scope(env->GetIsolate());
|
| @@ -16838,18 +17169,22 @@ void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
|
| ++prologue_call_count;
|
| }
|
|
|
| +
|
| void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
|
| ++epilogue_call_count;
|
| }
|
|
|
| +
|
| void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
|
| ++prologue_call_count_second;
|
| }
|
|
|
| +
|
| void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
|
| ++epilogue_call_count_second;
|
| }
|
|
|
| +
|
| TEST(GCCallbacks) {
|
| LocalContext context;
|
|
|
| @@ -17240,6 +17575,7 @@ TEST(GCInFailedAccessCheckCallback) {
|
| v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
|
| }
|
|
|
| +
|
| TEST(DefaultIsolateGetCurrent) {
|
| CHECK(v8::Isolate::GetCurrent() != NULL);
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| @@ -17247,6 +17583,7 @@ TEST(DefaultIsolateGetCurrent) {
|
| printf("*** %s\n", "DefaultIsolateGetCurrent success");
|
| }
|
|
|
| +
|
| TEST(IsolateNewDispose) {
|
| v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
|
| v8::Isolate* isolate = v8::Isolate::New();
|
| @@ -17262,6 +17599,7 @@ TEST(IsolateNewDispose) {
|
| CHECK_EQ(last_message, NULL);
|
| }
|
|
|
| +
|
| TEST(IsolateEnterExitDefault) {
|
| v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
|
| CHECK(current_isolate != NULL); // Default isolate.
|
| @@ -17280,6 +17618,7 @@ TEST(IsolateEnterExitDefault) {
|
| ExpectString("'still working 3'", "still working 3");
|
| }
|
|
|
| +
|
| TEST(DisposeDefaultIsolate) {
|
| v8::V8::SetFatalErrorHandler(StoringErrorCallback);
|
|
|
| @@ -17297,6 +17636,7 @@ TEST(DisposeDefaultIsolate) {
|
| CHECK_NE(last_message, NULL);
|
| }
|
|
|
| +
|
| TEST(RunDefaultAndAnotherIsolate) {
|
| v8::HandleScope scope(v8::Isolate::GetCurrent());
|
| LocalContext context;
|
| @@ -17339,6 +17679,7 @@ TEST(RunDefaultAndAnotherIsolate) {
|
| ExpectTrue("function f() { return bar == 371; }; f()");
|
| }
|
|
|
| +
|
| TEST(DisposeIsolateWhenInUse) {
|
| v8::Isolate* isolate = v8::Isolate::New();
|
| CHECK(isolate);
|
| @@ -17355,6 +17696,7 @@ TEST(DisposeIsolateWhenInUse) {
|
| CHECK_NE(last_message, NULL);
|
| }
|
|
|
| +
|
| TEST(RunTwoIsolatesOnSingleThread) {
|
| // Run isolate 1.
|
| v8::Isolate* isolate1 = v8::Isolate::New();
|
| @@ -17479,6 +17821,7 @@ TEST(RunTwoIsolatesOnSingleThread) {
|
| }
|
| }
|
|
|
| +
|
| static int CalcFibonacci(v8::Isolate* isolate, int limit) {
|
| v8::Isolate::Scope isolate_scope(isolate);
|
| v8::HandleScope scope(isolate);
|
| @@ -17514,6 +17857,7 @@ class IsolateThread : public v8::internal::Thread {
|
| int result_;
|
| };
|
|
|
| +
|
| TEST(MultipleIsolatesOnIndividualThreads) {
|
| v8::Isolate* isolate1 = v8::Isolate::New();
|
| v8::Isolate* isolate2 = v8::Isolate::New();
|
| @@ -17542,6 +17886,7 @@ TEST(MultipleIsolatesOnIndividualThreads) {
|
| isolate2->Dispose();
|
| }
|
|
|
| +
|
| TEST(IsolateDifferentContexts) {
|
| v8::Isolate* isolate = v8::Isolate::New();
|
| Local<v8::Context> context;
|
| @@ -17630,26 +17975,32 @@ static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
|
| CHECK_EQ(thread.result(), true);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread1) {
|
| InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread2) {
|
| InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread3) {
|
| InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread4) {
|
| InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread5) {
|
| InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
|
| }
|
|
|
| +
|
| TEST(InitializeDefaultIsolateOnSecondaryThread6) {
|
| InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
|
| }
|
|
|