Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(999)

Unified Diff: test/cctest/test-api.cc

Issue 148503002: A64: Synchronize with r15545. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/test-accessors.cc ('k') | test/cctest/test-assembler-a64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « test/cctest/test-accessors.cc ('k') | test/cctest/test-assembler-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698