From eaa95c523bb09ab9d396a04a0ba1778dcf1d012b Mon Sep 17 00:00:00 2001 From: "serya@chromium.org" Date: Thu, 6 May 2010 10:50:22 +0000 Subject: [PATCH] Inlined load of string.length and array.length. http://compute1.aar:9013/golem/r4583-v8-serya-length-inlined-vs-4583-v8.html Review URL: http://codereview.chromium.org/1917006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4601 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/debug.cc | 9 +++++++-- src/ic.cc | 14 ++++++++++++-- src/ic.h | 6 +++--- test/cctest/test-debug.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/debug.cc b/src/debug.cc index 18c321b..bf1f893 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -430,8 +430,13 @@ void BreakLocationIterator::SetDebugBreakAtIC() { // is set the patching performed by the runtime system will take place in // the code copy and will therefore have no effect on the running code // keeping it from using the inlined code. - if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc()); - if (code->is_keyed_store_stub()) KeyedStoreIC::ClearInlinedVersion(pc()); + if (code->is_keyed_load_stub()) { + KeyedLoadIC::ClearInlinedVersion(pc()); + } else if (code->is_keyed_store_stub()) { + KeyedStoreIC::ClearInlinedVersion(pc()); + } else if (code->is_load_stub()) { + LoadIC::ClearInlinedVersion(pc()); + } } } diff --git a/src/ic.cc b/src/ic.cc index 64c3ec1..678876d 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -596,10 +596,16 @@ Object* LoadIC::Load(State state, Handle object, Handle name) { #ifdef DEBUG if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); #endif + Map* map = HeapObject::cast(*object)->map(); + if (object->IsString()) { + const int offset = String::kLengthOffset; + PatchInlinedLoad(address(), map, offset); + } + Code* target = NULL; target = Builtins::builtin(Builtins::LoadIC_StringLength); set_target(target); - StubCache::Set(*name, HeapObject::cast(*object)->map(), target); + StubCache::Set(*name, map, target); return Smi::FromInt(String::cast(*object)->length()); } @@ -608,9 +614,13 @@ Object* LoadIC::Load(State state, Handle object, Handle name) { #ifdef DEBUG if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); #endif + Map* map = HeapObject::cast(*object)->map(); + const int offset = JSArray::kLengthOffset; + PatchInlinedLoad(address(), map, offset); + Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength); set_target(target); - StubCache::Set(*name, HeapObject::cast(*object)->map(), target); + StubCache::Set(*name, map, target); return JSArray::cast(*object)->length(); } diff --git a/src/ic.h b/src/ic.h index 6aae096..a7ff6e6 100644 --- a/src/ic.h +++ b/src/ic.h @@ -239,6 +239,9 @@ class LoadIC: public IC { static void GenerateStringLength(MacroAssembler* masm); static void GenerateFunctionPrototype(MacroAssembler* masm); + // Clear the use of the inlined version. + static void ClearInlinedVersion(Address address); + // The offset from the inlined patch site to the start of the // inlined load instruction. It is architecture-dependent, and not // used on ARM. @@ -265,9 +268,6 @@ class LoadIC: public IC { static void Clear(Address address, Code* target); - // Clear the use of the inlined version. - static void ClearInlinedVersion(Address address); - static bool PatchInlinedLoad(Address address, Object* map, int index); friend class IC; diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index cdc7ac1..d90be8e 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -2511,6 +2511,50 @@ TEST(DebugStepKeyedStoreLoop) { } +// Test of the stepping mechanism for named load in a loop. +TEST(DebugStepNamedLoadLoop) { + v8::HandleScope scope; + DebugLocalContext env; + + // Create a function for testing stepping of named load. + v8::Local foo = CompileFunction( + &env, + "function foo() {\n" + " var a = [];\n" + " var s = \"\";\n" + " for (var i = 0; i < 10; i++) {\n" + " var v = new V(i, i + 1);\n" + " v.y;\n" + " a.length;\n" // Special case: array length. + " s.length;\n" // Special case: string length. + " }\n" + "}\n" + "function V(x, y) {\n" + " this.x = x;\n" + " this.y = y;\n" + "}\n", + "foo"); + + // Call function without any break points to ensure inlining is in place. + foo->Call(env->Global(), 0, NULL); + + // Register a debug event listener which steps and counts. + v8::Debug::SetDebugEventListener(DebugEventStep); + + // Setup break point and step through the function. + SetBreakPoint(foo, 4); + step_action = StepNext; + break_point_hit_count = 0; + foo->Call(env->Global(), 0, NULL); + + // With stepping all break locations are hit. + CHECK_EQ(41, break_point_hit_count); + + v8::Debug::SetDebugEventListener(NULL); + CheckDebuggerUnloaded(); +} + + // Test the stepping mechanism with different ICs. TEST(DebugStepLinearMixedICs) { v8::HandleScope scope; -- 2.7.4