Author: [EMAIL PROTECTED]
Date: Sun Nov 16 21:50:52 2008
New Revision: 764

Modified:
    branches/bleeding_edge/src/ast.h
    branches/bleeding_edge/src/codegen-arm.h
    branches/bleeding_edge/src/codegen-ia32.cc
    branches/bleeding_edge/src/codegen-ia32.h
    branches/bleeding_edge/src/codegen.cc
    branches/bleeding_edge/src/codegen.h
    branches/bleeding_edge/src/compiler.cc
    branches/bleeding_edge/src/compiler.h
    branches/bleeding_edge/src/debug.cc
    branches/bleeding_edge/src/globals.h
    branches/bleeding_edge/src/handles.cc
    branches/bleeding_edge/src/handles.h
    branches/bleeding_edge/src/ic.cc
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/runtime.cc
    branches/bleeding_edge/src/stub-cache.cc
    branches/bleeding_edge/src/stub-cache.h

Log:
Track loop nesting across function calls when the function
is called through an IC the first time.
Review URL: http://codereview.chromium.org/10746

Modified: branches/bleeding_edge/src/ast.h
==============================================================================
--- branches/bleeding_edge/src/ast.h    (original)
+++ branches/bleeding_edge/src/ast.h    Sun Nov 16 21:50:52 2008
@@ -1125,6 +1125,7 @@
          start_position_(start_position),
          end_position_(end_position),
          is_expression_(is_expression),
+        loop_nesting_(0),
          function_token_position_(RelocInfo::kNoPosition) {
    }

@@ -1149,6 +1150,9 @@

    bool AllowsLazyCompilation();

+  bool loop_nesting() const { return loop_nesting_; }
+  void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
+
   private:
    Handle<String> name_;
    Scope* scope_;
@@ -1160,6 +1164,7 @@
    int start_position_;
    int end_position_;
    bool is_expression_;
+  int loop_nesting_;
    int function_token_position_;
  };


Modified: branches/bleeding_edge/src/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.h    (original)
+++ branches/bleeding_edge/src/codegen-arm.h    Sun Nov 16 21:50:52 2008
@@ -296,6 +296,7 @@
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

    Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);

    // Declare global variables and functions in the given array of
    // name/value pairs.

Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc  (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc  Sun Nov 16 21:50:52 2008
@@ -197,6 +197,10 @@
    VirtualFrame virtual_frame(this);
    frame_ = &virtual_frame;
    cc_reg_ = no_condition;
+
+  // Adjust for function-level loop nesting.
+  loop_nesting_ += fun->loop_nesting();
+
    {
      CodeGenState state(this);

@@ -383,11 +387,15 @@
      }
    }

+  // Adjust for function-level loop nesting.
+  loop_nesting_ -= fun->loop_nesting();
+
    // Code generation state must be reset.
    scope_ = NULL;
    frame_ = NULL;
    ASSERT(!has_cc());
    ASSERT(state_ == NULL);
+  ASSERT(loop_nesting() == 0);
  }


@@ -2694,14 +2702,15 @@
      // patch the stack to use the global proxy as 'this' in the
      // invoked function.
      LoadGlobal();
-
      // Load the arguments.
      for (int i = 0; i < args->length(); i++) {
        Load(args->at(i));
      }

      // Setup the receiver register and call the IC initialization code.
-    Handle<Code> stub = ComputeCallInitialize(args->length());
+    Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
      __ RecordPosition(node->position());
      __ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
      __ mov(esi, frame_->Context());
@@ -2745,7 +2754,9 @@
        for (int i = 0; i < args->length(); i++) Load(args->at(i));

        // Call the IC initialization code.
-      Handle<Code> stub = ComputeCallInitialize(args->length());
+      Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
        __ RecordPosition(node->position());
        __ call(stub, RelocInfo::CODE_TARGET);
        __ mov(esi, frame_->Context());

Modified: branches/bleeding_edge/src/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.h   (original)
+++ branches/bleeding_edge/src/codegen-ia32.h   Sun Nov 16 21:50:52 2008
@@ -320,6 +320,7 @@
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

    Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);

    // Declare global variables and functions in the given array of
    // name/value pairs.

Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc       (original)
+++ branches/bleeding_edge/src/codegen.cc       Sun Nov 16 21:50:52 2008
@@ -242,6 +242,15 @@
  }


+Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) {
+  // Force the creation of the corresponding stub outside loops,
+  // because it will be used when clearing the ICs later - when we
+  // don't know if we're inside a loop or not.
+  ComputeCallInitialize(argc);
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code);
+}
+
+
  void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>*  
declarations) {
    int length = declarations->length();
    int globals = 0;

Modified: branches/bleeding_edge/src/codegen.h
==============================================================================
--- branches/bleeding_edge/src/codegen.h        (original)
+++ branches/bleeding_edge/src/codegen.h        Sun Nov 16 21:50:52 2008
@@ -48,6 +48,7 @@
  // CodeGenerator::GenCode
  // CodeGenerator::BuildBoilerplate
  // CodeGenerator::ComputeCallInitialize
+// CodeGenerator::ComputeCallInitializeInLoop
  // CodeGenerator::ProcessDeclarations
  // CodeGenerator::DeclareGlobals
  // CodeGenerator::CheckForInlineRuntimeCall

Modified: branches/bleeding_edge/src/compiler.cc
==============================================================================
--- branches/bleeding_edge/src/compiler.cc      (original)
+++ branches/bleeding_edge/src/compiler.cc      Sun Nov 16 21:50:52 2008
@@ -239,7 +239,8 @@
  }


-bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
+bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+                           int loop_nesting) {
    ZoneScope zone_scope(DELETE_ON_EXIT);

    // The VM is in the COMPILER state until exiting this function.
@@ -270,6 +271,9 @@
      ASSERT(Top::has_pending_exception());
      return false;
    }
+
+  // Update the loop nesting in the function literal.
+  lit->set_loop_nesting(loop_nesting);

    // Measure how long it takes to do the lazy compilation; only take
    // the rest of the function into account to avoid overlap with the

Modified: branches/bleeding_edge/src/compiler.h
==============================================================================
--- branches/bleeding_edge/src/compiler.h       (original)
+++ branches/bleeding_edge/src/compiler.h       Sun Nov 16 21:50:52 2008
@@ -64,7 +64,7 @@
    // Compile from function info (used for lazy compilation). Returns
    // true on success and false if the compilation resulted in a stack
    // overflow.
-  static bool CompileLazy(Handle<SharedFunctionInfo> shared);
+  static bool CompileLazy(Handle<SharedFunctionInfo> shared, int  
loop_nesting);
  };

  } }  // namespace v8::internal

Modified: branches/bleeding_edge/src/debug.cc
==============================================================================
--- branches/bleeding_edge/src/debug.cc (original)
+++ branches/bleeding_edge/src/debug.cc Sun Nov 16 21:50:52 2008
@@ -1135,7 +1135,7 @@

  bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
    if (shared->is_compiled()) return true;
-  return CompileLazyShared(shared, CLEAR_EXCEPTION);
+  return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
  }



Modified: branches/bleeding_edge/src/globals.h
==============================================================================
--- branches/bleeding_edge/src/globals.h        (original)
+++ branches/bleeding_edge/src/globals.h        Sun Nov 16 21:50:52 2008
@@ -282,6 +282,8 @@
  enum InlineCacheState {
    // Has never been executed.
    UNINITIALIZED,
+  // Has never been executed, but is in a loop.
+  UNINITIALIZED_IN_LOOP,
    // Has been executed but monomorhic state has been delayed.
    PREMONOMORPHIC,
    // Has been executed and only one receiver type has been seen.

Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc       (original)
+++ branches/bleeding_edge/src/handles.cc       Sun Nov 16 21:50:52 2008
@@ -422,10 +422,11 @@


  bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag) {
+                       ClearExceptionFlag flag,
+                       int loop_nesting) {
    // Compile the source information to a code object.
    ASSERT(!shared->is_compiled());
-  bool result = Compiler::CompileLazy(shared);
+  bool result = Compiler::CompileLazy(shared, loop_nesting);
    ASSERT(result != Top::has_pending_exception());
    if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
    return result;
@@ -435,9 +436,15 @@
  bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
    // Compile the source information to a code object.
    Handle<SharedFunctionInfo> shared(function->shared());
-  return CompileLazyShared(shared, flag);
+  return CompileLazyShared(shared, flag, 0);
  }

+
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag  
flag) {
+  // Compile the source information to a code object.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  return CompileLazyShared(shared, flag, 1);
+}

  OptimizedObjectForAddingMultipleProperties::
  OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,

Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h        (original)
+++ branches/bleeding_edge/src/handles.h        Sun Nov 16 21:50:52 2008
@@ -194,9 +194,13 @@
  // Do lazy compilation of the given function. Returns true on success
  // and false if the compilation resulted in a stack overflow.
  enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+
  bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag);
+                       ClearExceptionFlag flag,
+                       int loop_nesting);
+
  bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag  
flag);

  // These deal with lazily loaded properties.
  void SetupLazy(Handle<JSFunction> fun,

Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc    (original)
+++ branches/bleeding_edge/src/ic.cc    Sun Nov 16 21:50:52 2008
@@ -41,6 +41,7 @@
  static char TransitionMarkFromState(IC::State state) {
    switch (state) {
      case UNINITIALIZED: return '0';
+    case UNINITIALIZED_IN_LOOP: return 'L';
      case PREMONOMORPHIC: return '0';
      case MONOMORPHIC: return '1';
      case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -223,7 +224,8 @@


  void CallIC::Clear(Address address, Code* target) {
-  if (target->ic_state() == UNINITIALIZED) return;
+  State state = target->ic_state();
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
    Code* code = StubCache::FindCallInitialize(target->arguments_count());
    SetTargetAtAddress(address, code);
  }
@@ -434,8 +436,9 @@
    if (code->IsFailure()) return;

    // Patch the call site depending on the state of the cache.
-  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
-      state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
+      state == PREMONOMORPHIC || state == MONOMORPHIC ||
+      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
      set_target(Code::cast(code));
    }

@@ -1044,7 +1047,17 @@
    ASSERT(args.length() == 2);
    CallIC ic;
    IC::State state = IC::StateFrom(ic.target(), args[0]);
-  return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  Object* result =
+      ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+    return result;
+
+  // Compile the function with the knowledge that it's called from
+  // within a loop. This enables further optimization of the function.
+  HandleScope scope;
+  Handle<JSFunction> function =  
Handle<JSFunction>(JSFunction::cast(result));
+  if (!function->is_compiled()) CompileLazyInLoop(function,  
CLEAR_EXCEPTION);
+  return *function;
  }



Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Sun Nov 16 21:50:52 2008
@@ -4603,6 +4603,7 @@
  const char* Code::ICState2String(InlineCacheState state) {
    switch (state) {
      case UNINITIALIZED: return "UNINITIALIZED";
+    case UNINITIALIZED_IN_LOOP: return "UNINITIALIZED_IN_LOOP";
      case PREMONOMORPHIC: return "PREMONOMORPHIC";
      case MONOMORPHIC: return "MONOMORPHIC";
      case MONOMORPHIC_PROTOTYPE_FAILURE:  
return "MONOMORPHIC_PROTOTYPE_FAILURE";

Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc       (original)
+++ branches/bleeding_edge/src/runtime.cc       Sun Nov 16 21:50:52 2008
@@ -5088,7 +5088,7 @@
      if (!done) {
        // If the candidate is not compiled compile it to reveal any inner
        // functions which might contain the requested source position.
-      CompileLazyShared(target, KEEP_EXCEPTION);
+      CompileLazyShared(target, KEEP_EXCEPTION, 0);
      }
    }


Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc    (original)
+++ branches/bleeding_edge/src/stub-cache.cc    Sun Nov 16 21:50:52 2008
@@ -543,6 +543,17 @@
  }


+Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED_IN_LOOP, NORMAL,  
argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+
  Object* StubCache::ComputeCallPreMonomorphic(int argc) {
    Code::Flags flags =
        Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);

Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h     (original)
+++ branches/bleeding_edge/src/stub-cache.h     Sun Nov 16 21:50:52 2008
@@ -148,6 +148,7 @@
    // ---

    static Object* ComputeCallInitialize(int argc);
+  static Object* ComputeCallInitializeInLoop(int argc);
    static Object* ComputeCallPreMonomorphic(int argc);
    static Object* ComputeCallNormal(int argc);
    static Object* ComputeCallMegamorphic(int argc);

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to