| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 | 27 | 
| 28 #include <limits.h> | 28 #include <limits.h> | 
| 29 | 29 | 
| 30 #ifndef WIN32 | 30 #ifndef WIN32 | 
| 31 #include <signal.h>  // kill | 31 #include <signal.h>  // kill | 
| 32 #include <unistd.h>  // getpid | 32 #include <unistd.h>  // getpid | 
| 33 #endif  // WIN32 | 33 #endif  // WIN32 | 
|  | 34 #include <string> | 
|  | 35 #include <map> | 
| 34 | 36 | 
| 35 #include "v8.h" | 37 #include "v8.h" | 
| 36 | 38 | 
| 37 #include "api.h" | 39 #include "api.h" | 
| 38 #include "arguments.h" | 40 #include "arguments.h" | 
| 39 #include "isolate.h" | 41 #include "isolate.h" | 
| 40 #include "compilation-cache.h" | 42 #include "compilation-cache.h" | 
| 41 #include "execution.h" | 43 #include "execution.h" | 
| 42 #include "objects.h" | 44 #include "objects.h" | 
| 43 #include "snapshot.h" | 45 #include "snapshot.h" | 
| (...skipping 12221 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 12265   v8::HandleScope outer(isolate); | 12267   v8::HandleScope outer(isolate); | 
| 12266   v8::Local<Context> env = Context::New(isolate); | 12268   v8::Local<Context> env = Context::New(isolate); | 
| 12267   env->Enter(); | 12269   env->Enter(); | 
| 12268   v8::Handle<Value> value = NestedScope(env); | 12270   v8::Handle<Value> value = NestedScope(env); | 
| 12269   v8::Handle<String> str(value->ToString()); | 12271   v8::Handle<String> str(value->ToString()); | 
| 12270   CHECK(!str.IsEmpty()); | 12272   CHECK(!str.IsEmpty()); | 
| 12271   env->Exit(); | 12273   env->Exit(); | 
| 12272 } | 12274 } | 
| 12273 | 12275 | 
| 12274 | 12276 | 
| 12275 static i::Handle<i::JSFunction>* foo_ptr = NULL; | 12277 static bool MatchPointers(void* key1, void* key2) { | 
| 12276 static int foo_entry_count = 0; | 12278   return key1 == key2; | 
| 12277 static i::Handle<i::JSFunction>* bar_ptr = NULL; | 12279 } | 
| 12278 static int bar_entry_count = 0; | 12280 | 
| 12279 static int bar_caller_count = 0; | 12281 | 
| 12280 | 12282 struct SymbolInfo { | 
| 12281 | 12283   size_t id; | 
| 12282 static void entry_hook(uintptr_t function, | 12284   size_t size; | 
| 12283                        uintptr_t return_addr_location) { | 12285   std::string name; | 
| 12284   i::Code* code = i::Code::GetCodeFromTargetAddress( | 12286 }; | 
|  | 12287 | 
|  | 12288 | 
|  | 12289 class SetFunctionEntryHookTest { | 
|  | 12290  public: | 
|  | 12291   SetFunctionEntryHookTest() { | 
|  | 12292     CHECK(instance_ == NULL); | 
|  | 12293     instance_ = this; | 
|  | 12294   } | 
|  | 12295   ~SetFunctionEntryHookTest() { | 
|  | 12296     CHECK(instance_ == this); | 
|  | 12297     instance_ = NULL; | 
|  | 12298   } | 
|  | 12299   void Reset() { | 
|  | 12300     symbols_.clear(); | 
|  | 12301     symbol_locations_.clear(); | 
|  | 12302     invocations_.clear(); | 
|  | 12303   } | 
|  | 12304   void RunTest(); | 
|  | 12305   void OnJitEvent(const v8::JitCodeEvent* event); | 
|  | 12306   static void JitEvent(const v8::JitCodeEvent* event) { | 
|  | 12307     CHECK(instance_ != NULL); | 
|  | 12308     instance_->OnJitEvent(event); | 
|  | 12309   } | 
|  | 12310 | 
|  | 12311   void OnEntryHook(uintptr_t function, | 
|  | 12312                    uintptr_t return_addr_location); | 
|  | 12313   static void EntryHook(uintptr_t function, | 
|  | 12314                         uintptr_t return_addr_location) { | 
|  | 12315     CHECK(instance_ != NULL); | 
|  | 12316     instance_->OnEntryHook(function, return_addr_location); | 
|  | 12317   } | 
|  | 12318 | 
|  | 12319   v8::Handle<Value> OnRuntimeCallback(const v8::Arguments& args); | 
|  | 12320   static v8::Handle<Value> RuntimeCallback(const v8::Arguments& args) { | 
|  | 12321     CHECK(instance_ != NULL); | 
|  | 12322     return instance_->OnRuntimeCallback(args); | 
|  | 12323   } | 
|  | 12324   void RunLoopInNewEnv(v8::Isolate* isolate); | 
|  | 12325 | 
|  | 12326   // Records addr as location of symbol. | 
|  | 12327   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol); | 
|  | 12328 | 
|  | 12329   // Finds the symbol containing addr | 
|  | 12330   SymbolInfo* FindSymbolForAddr(i::Address addr); | 
|  | 12331   // Returns the number of invocations where the caller name contains | 
|  | 12332   // \p caller_name and the function name contains \p function_name. | 
|  | 12333   size_t CountInvocations(const char* caller_name, | 
|  | 12334                           const char* function_name); | 
|  | 12335 | 
|  | 12336   i::Handle<i::JSFunction> foo_func_; | 
|  | 12337   i::Handle<i::JSFunction> bar_func_; | 
|  | 12338 | 
|  | 12339   typedef std::map<size_t, SymbolInfo> SymbolMap; | 
|  | 12340   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap; | 
|  | 12341   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, size_t> InvocationMap; | 
|  | 12342   SymbolMap symbols_; | 
|  | 12343   SymbolLocationMap symbol_locations_; | 
|  | 12344   InvocationMap invocations_; | 
|  | 12345 | 
|  | 12346   static SetFunctionEntryHookTest* instance_; | 
|  | 12347 }; | 
|  | 12348 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL; | 
|  | 12349 | 
|  | 12350 | 
|  | 12351 // Returns true if addr is in the range [start, start+len). | 
|  | 12352 static bool Overlaps(i::Address start, size_t len, i::Address addr) { | 
|  | 12353   if (start <= addr && start + len > addr) | 
|  | 12354     return true; | 
|  | 12355 | 
|  | 12356   return false; | 
|  | 12357 } | 
|  | 12358 | 
|  | 12359 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr, | 
|  | 12360                                               SymbolInfo* symbol) { | 
|  | 12361   // Insert the symbol at the new location. | 
|  | 12362   SymbolLocationMap::iterator it = | 
|  | 12363       symbol_locations_.insert(std::make_pair(addr, symbol)).first; | 
|  | 12364   // Now erase symbols to the left and right that overlap this one. | 
|  | 12365   while (it != symbol_locations_.begin()) { | 
|  | 12366     SymbolLocationMap::iterator left = it; | 
|  | 12367     --left; | 
|  | 12368     if (!Overlaps(left->first, left->second->size, addr)) | 
|  | 12369       break; | 
|  | 12370     symbol_locations_.erase(left); | 
|  | 12371   } | 
|  | 12372 | 
|  | 12373   // Now erase symbols to the left and right that overlap this one. | 
|  | 12374   while (true) { | 
|  | 12375     SymbolLocationMap::iterator right = it; | 
|  | 12376     ++right; | 
|  | 12377     if (right == symbol_locations_.end()) | 
|  | 12378         break; | 
|  | 12379     if (!Overlaps(addr, symbol->size, right->first)) | 
|  | 12380       break; | 
|  | 12381     symbol_locations_.erase(right); | 
|  | 12382   } | 
|  | 12383 } | 
|  | 12384 | 
|  | 12385 | 
|  | 12386 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) { | 
|  | 12387   switch (event->type) { | 
|  | 12388     case v8::JitCodeEvent::CODE_ADDED: { | 
|  | 12389         CHECK(event->code_start != NULL); | 
|  | 12390         CHECK_NE(0, static_cast<int>(event->code_len)); | 
|  | 12391         CHECK(event->name.str != NULL); | 
|  | 12392         size_t symbol_id = symbols_.size(); | 
|  | 12393 | 
|  | 12394         // Record the new symbol. | 
|  | 12395         SymbolInfo& info = symbols_[symbol_id]; | 
|  | 12396         info.id = symbol_id; | 
|  | 12397         info.size = event->code_len; | 
|  | 12398         info.name.assign(event->name.str, event->name.str + event->name.len); | 
|  | 12399 | 
|  | 12400         // And record it's location. | 
|  | 12401         InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info); | 
|  | 12402       } | 
|  | 12403       break; | 
|  | 12404 | 
|  | 12405     case v8::JitCodeEvent::CODE_MOVED: { | 
|  | 12406         // We would like to never see code move that we haven't seen before, | 
|  | 12407         // but the code creation event does not happen until the line endings | 
|  | 12408         // have been calculated (this is so that we can report the line in the | 
|  | 12409         // script at which the function source is found, see | 
|  | 12410         // Compiler::RecordFunctionCompilation) and the line endings | 
|  | 12411         // calculations can cause a GC, which can move the newly created code | 
|  | 12412         // before its existence can be logged. | 
|  | 12413         SymbolLocationMap::iterator it( | 
|  | 12414             symbol_locations_.find( | 
|  | 12415                 reinterpret_cast<i::Address>(event->code_start))); | 
|  | 12416         if (it != symbol_locations_.end()) { | 
|  | 12417           // Found a symbol at this location, move it. | 
|  | 12418           SymbolInfo* info = it->second; | 
|  | 12419           symbol_locations_.erase(it); | 
|  | 12420           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start), | 
|  | 12421                          info); | 
|  | 12422         } | 
|  | 12423       } | 
|  | 12424     default: | 
|  | 12425       break; | 
|  | 12426   } | 
|  | 12427 } | 
|  | 12428 | 
|  | 12429 void SetFunctionEntryHookTest::OnEntryHook( | 
|  | 12430     uintptr_t function, uintptr_t return_addr_location) { | 
|  | 12431   // Get the function's code object. | 
|  | 12432   i::Code* function_code = i::Code::GetCodeFromTargetAddress( | 
| 12285       reinterpret_cast<i::Address>(function)); | 12433       reinterpret_cast<i::Address>(function)); | 
| 12286   CHECK(code != NULL); | 12434   CHECK(function_code != NULL); | 
| 12287 | 12435 | 
| 12288   if (bar_ptr != NULL && code == (*bar_ptr)->code()) | 12436   // Then try and look up the caller's code object. | 
| 12289     ++bar_entry_count; | 12437   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location); | 
| 12290 | 12438 | 
| 12291   if (foo_ptr != NULL && code == (*foo_ptr)->code()) | 12439   // Count the invocation. | 
| 12292     ++foo_entry_count; | 12440   SymbolInfo* caller_symbol = FindSymbolForAddr(caller); | 
| 12293 | 12441   SymbolInfo* function_symbol = | 
| 12294   // Let's check whether bar is the caller. | 12442       FindSymbolForAddr(reinterpret_cast<i::Address>(function)); | 
| 12295   if (bar_ptr != NULL) { | 12443   ++invocations_[std::make_pair(caller_symbol, function_symbol)]; | 
| 12296     const v8::internal::byte* caller = | 12444 | 
| 12297         *reinterpret_cast<v8::internal::byte**>(return_addr_location); | 12445   if (!bar_func_.is_null() && function_code == bar_func_->code()) { | 
| 12298 | 12446     // Check that we have a symbol for the "bar" function at the right location. | 
| 12299     if ((*bar_ptr)->code()->instruction_start() <= caller && | 12447     SymbolLocationMap::iterator it( | 
| 12300         (*bar_ptr)->code()->instruction_end() > caller) { | 12448         symbol_locations_.find(function_code->instruction_start())); | 
| 12301       ++bar_caller_count; | 12449     CHECK(it != symbol_locations_.end()); | 
|  | 12450   } | 
|  | 12451 | 
|  | 12452   if (!foo_func_.is_null() && function_code == foo_func_->code()) { | 
|  | 12453     // Check that we have a symbol for "foo" at the right location. | 
|  | 12454     SymbolLocationMap::iterator it( | 
|  | 12455         symbol_locations_.find(function_code->instruction_start())); | 
|  | 12456     CHECK(it != symbol_locations_.end()); | 
|  | 12457   } | 
|  | 12458 } | 
|  | 12459 | 
|  | 12460 | 
|  | 12461 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) { | 
|  | 12462   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr)); | 
|  | 12463   // Do we have a direct hit on a symbol? | 
|  | 12464   if (it != symbol_locations_.end()) { | 
|  | 12465     if (it->first == addr) | 
|  | 12466       return it->second; | 
|  | 12467   } | 
|  | 12468 | 
|  | 12469   // If not a direct hit, it'll have to be the previous symbol. | 
|  | 12470   if (it == symbol_locations_.begin()) | 
|  | 12471     return NULL; | 
|  | 12472 | 
|  | 12473   --it; | 
|  | 12474   size_t offs = addr - it->first; | 
|  | 12475   if (offs < it->second->size) | 
|  | 12476     return it->second; | 
|  | 12477 | 
|  | 12478   return NULL; | 
|  | 12479 } | 
|  | 12480 | 
|  | 12481 | 
|  | 12482 v8::Handle<Value> SetFunctionEntryHookTest::OnRuntimeCallback( | 
|  | 12483       const v8::Arguments& args) { | 
|  | 12484   return v8_num(42); | 
|  | 12485 } | 
|  | 12486 | 
|  | 12487 | 
|  | 12488 size_t SetFunctionEntryHookTest::CountInvocations( | 
|  | 12489     const char* caller_name, const char* function_name) { | 
|  | 12490   InvocationMap::iterator it(invocations_.begin()); | 
|  | 12491   size_t invocations = 0; | 
|  | 12492   for (; it != invocations_.end(); ++it) { | 
|  | 12493     SymbolInfo* caller = it->first.first; | 
|  | 12494     SymbolInfo* function = it->first.second; | 
|  | 12495 | 
|  | 12496     // Filter out non-matching functions. | 
|  | 12497     if (function_name != NULL) { | 
|  | 12498       if (function->name.find(function_name) == std::string::npos) | 
|  | 12499         continue; | 
| 12302     } | 12500     } | 
| 12303   } | 12501 | 
| 12304 } | 12502     // Filter out non-matching callers. | 
| 12305 | 12503     if (caller_name != NULL) { | 
| 12306 | 12504       if (caller == NULL) | 
| 12307 static void RunLoopInNewEnv() { | 12505         continue; | 
| 12308   bar_ptr = NULL; | 12506       if (caller->name.find(caller_name) == std::string::npos) | 
| 12309   foo_ptr = NULL; | 12507         continue; | 
| 12310 | 12508     } | 
| 12311   v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 12509 | 
|  | 12510     // It matches add the invocation count to the tally. | 
|  | 12511     invocations += it->second; | 
|  | 12512   } | 
|  | 12513 | 
|  | 12514   return invocations; | 
|  | 12515 } | 
|  | 12516 | 
|  | 12517 | 
|  | 12518 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) { | 
| 12312   v8::HandleScope outer(isolate); | 12519   v8::HandleScope outer(isolate); | 
| 12313   v8::Local<Context> env = Context::New(isolate); | 12520   v8::Local<Context> env = Context::New(isolate); | 
| 12314   env->Enter(); | 12521   env->Enter(); | 
| 12315 | 12522 | 
|  | 12523   Local<ObjectTemplate> t = ObjectTemplate::New(); | 
|  | 12524   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback)); | 
|  | 12525   env->Global()->Set(v8_str("obj"), t->NewInstance()); | 
|  | 12526 | 
| 12316   const char* script = | 12527   const char* script = | 
| 12317       "function bar() {" | 12528       "function bar() {\n" | 
| 12318       "  var sum = 0;" | 12529       "  var sum = 0;\n" | 
| 12319       "  for (i = 0; i < 100; ++i)" | 12530       "  for (i = 0; i < 100; ++i)\n" | 
| 12320       "    sum = foo(i);" | 12531       "    sum = foo(i);\n" | 
| 12321       "  return sum;" | 12532       "  return sum;\n" | 
| 12322       "}" | 12533       "}\n" | 
| 12323       "function foo(i) { return i * i; }"; | 12534       "function foo(i) { return i * i; }\n" | 
|  | 12535       "// Invoke on the runtime function.\n" | 
|  | 12536       "obj.asdf()"; | 
| 12324   CompileRun(script); | 12537   CompileRun(script); | 
| 12325   i::Handle<i::JSFunction> bar = | 12538   bar_func_ = i::Handle<i::JSFunction>::cast( | 
| 12326       i::Handle<i::JSFunction>::cast( |  | 
| 12327           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar")))); | 12539           v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar")))); | 
| 12328   ASSERT(*bar); | 12540   ASSERT(!bar_func_.is_null()); | 
| 12329 | 12541 | 
| 12330   i::Handle<i::JSFunction> foo = | 12542   foo_func_ = | 
| 12331       i::Handle<i::JSFunction>::cast( | 12543       i::Handle<i::JSFunction>::cast( | 
| 12332            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo")))); | 12544            v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo")))); | 
| 12333   ASSERT(*foo); | 12545   ASSERT(!foo_func_.is_null()); | 
| 12334 |  | 
| 12335   bar_ptr = &bar; |  | 
| 12336   foo_ptr = &foo; |  | 
| 12337 | 12546 | 
| 12338   v8::Handle<v8::Value> value = CompileRun("bar();"); | 12547   v8::Handle<v8::Value> value = CompileRun("bar();"); | 
| 12339   CHECK(value->IsNumber()); | 12548   CHECK(value->IsNumber()); | 
| 12340   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); | 12549   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); | 
| 12341 | 12550 | 
| 12342   // Test the optimized codegen path. | 12551   // Test the optimized codegen path. | 
| 12343   value = CompileRun("%OptimizeFunctionOnNextCall(foo);" | 12552   value = CompileRun("%OptimizeFunctionOnNextCall(foo);" | 
| 12344                      "bar();"); | 12553                      "bar();"); | 
| 12345   CHECK(value->IsNumber()); | 12554   CHECK(value->IsNumber()); | 
| 12346   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); | 12555   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value()); | 
| 12347 | 12556 | 
| 12348   env->Exit(); | 12557   env->Exit(); | 
| 12349 } | 12558 } | 
| 12350 | 12559 | 
|  | 12560 void SetFunctionEntryHookTest::RunTest() { | 
|  | 12561   // Work in a new isolate throughout. | 
|  | 12562   v8::Isolate* isolate = v8::Isolate::New(); | 
|  | 12563 | 
|  | 12564   // Test setting the entry hook on the new isolate. | 
|  | 12565   CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook)); | 
|  | 12566 | 
|  | 12567   // Replacing the hook, once set should fail. | 
|  | 12568   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook)); | 
|  | 12569 | 
|  | 12570   { | 
|  | 12571     v8::Isolate::Scope scope(isolate); | 
|  | 12572 | 
|  | 12573     v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent); | 
|  | 12574 | 
|  | 12575     RunLoopInNewEnv(isolate); | 
|  | 12576 | 
|  | 12577     // Check the exepected invocation counts. | 
|  | 12578     CHECK_EQ(2, CountInvocations(NULL, "bar")); | 
|  | 12579     CHECK_EQ(200, CountInvocations("bar", "foo")); | 
|  | 12580     CHECK_EQ(200, CountInvocations(NULL, "foo")); | 
|  | 12581 | 
|  | 12582     // Verify that we have an entry hook on some specific stubs. | 
|  | 12583     CHECK_NE(0, CountInvocations(NULL, "CEntryStub")); | 
|  | 12584     CHECK_NE(0, CountInvocations(NULL, "JSEntryStub")); | 
|  | 12585     CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline")); | 
|  | 12586   } | 
|  | 12587   isolate->Dispose(); | 
|  | 12588 | 
|  | 12589   Reset(); | 
|  | 12590 | 
|  | 12591   // Make sure a second isolate is unaffected by the previous entry hook. | 
|  | 12592   isolate = v8::Isolate::New(); | 
|  | 12593   { | 
|  | 12594     v8::Isolate::Scope scope(isolate); | 
|  | 12595 | 
|  | 12596     // Reset the entry count to zero and set the entry hook. | 
|  | 12597     RunLoopInNewEnv(isolate); | 
|  | 12598 | 
|  | 12599     // We should record no invocations in this isolate. | 
|  | 12600     CHECK_EQ(0, invocations_.size()); | 
|  | 12601   } | 
|  | 12602   // Since the isolate has been used, we shouldn't be able to set an entry | 
|  | 12603   // hook anymore. | 
|  | 12604   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook)); | 
|  | 12605 | 
|  | 12606   isolate->Dispose(); | 
|  | 12607 } | 
|  | 12608 | 
| 12351 | 12609 | 
| 12352 TEST(SetFunctionEntryHook) { | 12610 TEST(SetFunctionEntryHook) { | 
| 12353   // FunctionEntryHook does not work well with experimental natives. | 12611   // FunctionEntryHook does not work well with experimental natives. | 
| 12354   // Experimental natives are compiled during snapshot deserialization. | 12612   // Experimental natives are compiled during snapshot deserialization. | 
| 12355   // This test breaks because InstallGetter (function from snapshot that | 12613   // This test breaks because InstallGetter (function from snapshot that | 
| 12356   // only gets called from experimental natives) is compiled with entry hooks. | 12614   // only gets called from experimental natives) is compiled with entry hooks. | 
| 12357   i::FLAG_harmony_typed_arrays = false; | 12615   i::FLAG_harmony_typed_arrays = false; | 
| 12358   i::FLAG_harmony_array_buffer = false; | 12616   i::FLAG_harmony_array_buffer = false; | 
| 12359 | 12617 | 
| 12360   i::FLAG_allow_natives_syntax = true; | 12618   i::FLAG_allow_natives_syntax = true; | 
| 12361   i::FLAG_use_inlining = false; | 12619   i::FLAG_use_inlining = false; | 
| 12362 | 12620 | 
| 12363   // Test setting and resetting the entry hook. | 12621   SetFunctionEntryHookTest test; | 
| 12364   // Nulling it should always succeed. | 12622   test.RunTest(); | 
| 12365   CHECK(v8::V8::SetFunctionEntryHook(NULL)); |  | 
| 12366 |  | 
| 12367   CHECK(v8::V8::SetFunctionEntryHook(entry_hook)); |  | 
| 12368   // Setting a hook while one's active should fail. |  | 
| 12369   CHECK_EQ(false, v8::V8::SetFunctionEntryHook(entry_hook)); |  | 
| 12370 |  | 
| 12371   CHECK(v8::V8::SetFunctionEntryHook(NULL)); |  | 
| 12372 |  | 
| 12373   // Reset the entry count to zero and set the entry hook. |  | 
| 12374   bar_entry_count = 0; |  | 
| 12375   bar_caller_count = 0; |  | 
| 12376   foo_entry_count = 0; |  | 
| 12377   CHECK(v8::V8::SetFunctionEntryHook(entry_hook)); |  | 
| 12378   RunLoopInNewEnv(); |  | 
| 12379 |  | 
| 12380   CHECK_EQ(2, bar_entry_count); |  | 
| 12381   CHECK_EQ(200, bar_caller_count); |  | 
| 12382   CHECK_EQ(200, foo_entry_count); |  | 
| 12383 |  | 
| 12384   // Clear the entry hook and count. |  | 
| 12385   bar_entry_count = 0; |  | 
| 12386   bar_caller_count = 0; |  | 
| 12387   foo_entry_count = 0; |  | 
| 12388   v8::V8::SetFunctionEntryHook(NULL); |  | 
| 12389 |  | 
| 12390   // Clear the compilation cache to make sure we don't reuse the |  | 
| 12391   // functions from the previous invocation. |  | 
| 12392   v8::internal::Isolate::Current()->compilation_cache()->Clear(); |  | 
| 12393 |  | 
| 12394   // Verify that entry hooking is now disabled. |  | 
| 12395   RunLoopInNewEnv(); |  | 
| 12396   CHECK_EQ(0u, bar_entry_count); |  | 
| 12397   CHECK_EQ(0u, bar_caller_count); |  | 
| 12398   CHECK_EQ(0u, foo_entry_count); |  | 
| 12399 } | 12623 } | 
| 12400 | 12624 | 
| 12401 | 12625 | 
| 12402 static i::HashMap* code_map = NULL; | 12626 static i::HashMap* code_map = NULL; | 
| 12403 static i::HashMap* jitcode_line_info = NULL; | 12627 static i::HashMap* jitcode_line_info = NULL; | 
| 12404 static int saw_bar = 0; | 12628 static int saw_bar = 0; | 
| 12405 static int move_events = 0; | 12629 static int move_events = 0; | 
| 12406 | 12630 | 
| 12407 | 12631 | 
| 12408 static bool FunctionNameIs(const char* expected, | 12632 static bool FunctionNameIs(const char* expected, | 
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 12530       break; | 12754       break; | 
| 12531 | 12755 | 
| 12532     default: | 12756     default: | 
| 12533       // Impossible event. | 12757       // Impossible event. | 
| 12534       CHECK(false); | 12758       CHECK(false); | 
| 12535       break; | 12759       break; | 
| 12536   } | 12760   } | 
| 12537 } | 12761 } | 
| 12538 | 12762 | 
| 12539 | 12763 | 
| 12540 static bool MatchPointers(void* key1, void* key2) { |  | 
| 12541   return key1 == key2; |  | 
| 12542 } |  | 
| 12543 |  | 
| 12544 |  | 
| 12545 TEST(SetJitCodeEventHandler) { | 12764 TEST(SetJitCodeEventHandler) { | 
| 12546   i::FLAG_stress_compaction = true; | 12765   i::FLAG_stress_compaction = true; | 
| 12547   i::FLAG_incremental_marking = false; | 12766   i::FLAG_incremental_marking = false; | 
| 12548   const char* script = | 12767   const char* script = | 
| 12549     "function bar() {" | 12768     "function bar() {" | 
| 12550     "  var sum = 0;" | 12769     "  var sum = 0;" | 
| 12551     "  for (i = 0; i < 100; ++i)" | 12770     "  for (i = 0; i < 100; ++i)" | 
| 12552     "    sum = foo(i);" | 12771     "    sum = foo(i);" | 
| 12553     "  return sum;" | 12772     "  return sum;" | 
| 12554     "}" | 12773     "}" | 
| (...skipping 6806 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 19361   i::Semaphore* sem_; | 19580   i::Semaphore* sem_; | 
| 19362   volatile int sem_value_; | 19581   volatile int sem_value_; | 
| 19363 }; | 19582 }; | 
| 19364 | 19583 | 
| 19365 | 19584 | 
| 19366 THREADED_TEST(SemaphoreInterruption) { | 19585 THREADED_TEST(SemaphoreInterruption) { | 
| 19367   ThreadInterruptTest().RunTest(); | 19586   ThreadInterruptTest().RunTest(); | 
| 19368 } | 19587 } | 
| 19369 | 19588 | 
| 19370 #endif  // WIN32 | 19589 #endif  // WIN32 | 
| OLD | NEW | 
|---|