| 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); }
|
|
|
|
|
|
|