Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index 229607266004673f87054898df272440f22105f0..4eafd4ff250f025f2a38bf683a097b57fda862cd 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -33,6 +33,7 @@ |
#include "isolate.h" |
#include "compilation-cache.h" |
#include "execution.h" |
+#include "objects.h" |
#include "snapshot.h" |
#include "platform.h" |
#include "utils.h" |
@@ -10873,6 +10874,89 @@ THREADED_TEST(NestedHandleScopeAndContexts) { |
} |
+static size_t entry_count = 0; |
+static uint64_t last_cycles = 0; |
+ |
+ |
+static void entry_hook(intptr_t function, |
+ intptr_t stack_pointer, |
+ uint64_t entry_time) { |
+ CHECK(entry_time >= last_cycles); |
+ |
+ i::Code* code = i::Code::GetCodeFromTargetAddress( |
+ reinterpret_cast<i::Address>(function)); |
+ CHECK(code != NULL); |
+ |
+ // TODO(siggi): How can I reach back to the JS function objects and test |
+ // some of their properties (like name)? |
+ |
+ last_cycles = entry_time; |
+ ++entry_count; |
+} |
+ |
+ |
+static void RunLoopInNewEnv() { |
+ v8::HandleScope outer; |
+ v8::Persistent<Context> env = Context::New(); |
+ env->Enter(); |
+ |
+ 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; }" |
+ "bar();"; |
+ v8::Handle<v8::Value> value = CompileRun(script); |
+ CHECK(value->IsNumber()); |
+ CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); |
+ |
+ // Test the optimized codegen path. |
+ value = CompileRun("%OptimizeFunctionOnNextCall(foo);" |
+ "bar();"); |
+ CHECK(value->IsNumber()); |
+ CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); |
+ |
+ env->Exit(); |
+} |
+ |
+ |
+THREADED_TEST(SetFunctionEntryHook) { |
+ i::FLAG_allow_natives_syntax = true; |
+ |
+ // Test setting and resetting the entry hook. |
+ // Nulling it should alwasy 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. |
+ entry_count = 0; |
+ CHECK(v8::V8::SetFunctionEntryHook(entry_hook)); |
+ RunLoopInNewEnv(); |
+ // TODO(siggi): This will fail if ever V8 inlines the function foo() above. |
+ CHECK_LE(204, entry_count); |
+ |
+ // Clear the entry hook and count. |
+ 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(0u == entry_count); |
+} |
+ |
+ |
static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); } |