Author: [email protected]
Date: Mon May 25 11:29:02 2009
New Revision: 2046

Modified:
    branches/bleeding_edge/src/arm/codegen-arm.cc
    branches/bleeding_edge/src/arm/codegen-arm.h
    branches/bleeding_edge/src/arm/ic-arm.cc
    branches/bleeding_edge/src/arm/stub-cache-arm.cc
    branches/bleeding_edge/src/builtins.cc
    branches/bleeding_edge/src/code-stubs.cc
    branches/bleeding_edge/src/code-stubs.h
    branches/bleeding_edge/src/codegen.cc
    branches/bleeding_edge/src/globals.h
    branches/bleeding_edge/src/ia32/codegen-ia32.cc
    branches/bleeding_edge/src/ia32/codegen-ia32.h
    branches/bleeding_edge/src/ia32/ic-ia32.cc
    branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
    branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
    branches/bleeding_edge/src/ic.cc
    branches/bleeding_edge/src/ic.h
    branches/bleeding_edge/src/objects-inl.h
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/src/runtime.cc
    branches/bleeding_edge/src/stub-cache.cc
    branches/bleeding_edge/src/stub-cache.h

Log:
This patch much improves our tracking of whether function is
called from within a loop or not.  In the past we lost the
information if a call site went megamorphic before a lazily
compiled callee was called for the first time.  Now we track
that correctly (this is an issue that affects richards).
We still don't manage to track the in-loop state through a
constructor call, since constructor calls use LoadICs instead
of CallICs.  This issue affects delta-blue.  So in this patch
we assume that lazy compilations that don't happen through a
CallIC happen from inside a loop.  I have an idea to fix this
but this patch is big enough already.
With our improved tracking of in-loop state I have switched
off the inlining of in-object loads for code that is not in
a loop.  This benefits compile speed.  One issue is that
eagerly compiled code now doesn't get the in-object loads
inlined.  We need to eagerly compile less code to fix this.
Review URL: http://codereview.chromium.org/115744

Modified: branches/bleeding_edge/src/arm/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.cc       (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.cc       Mon May 25 11:29:02 2009
@@ -1058,12 +1058,14 @@

  class CallFunctionStub: public CodeStub {
   public:
-  explicit CallFunctionStub(int argc) : argc_(argc) {}
+  CallFunctionStub(int argc, InLoopFlag in_loop)
+      : argc_(argc), in_loop_(in_loop) {}

    void Generate(MacroAssembler* masm);

   private:
    int argc_;
+  InLoopFlag in_loop_;

  #if defined(DEBUG)
    void Print() { PrintF("CallFunctionStub (argc %d)\n", argc_); }
@@ -1071,6 +1073,7 @@

    Major MajorKey() { return CallFunction; }
    int MinorKey() { return argc_; }
+  InLoopFlag InLoop() { return in_loop_; }
  };


@@ -1088,7 +1091,8 @@
    CodeForSourcePosition(position);

    // Use the shared code stub to call the function.
-  CallFunctionStub call_function(arg_count);
+  InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+  CallFunctionStub call_function(arg_count, in_loop);
    frame_->CallStub(&call_function, arg_count + 1);

    // Restore context and pop function from the stack.
@@ -3051,7 +3055,8 @@
      }

      // Setup the receiver register and call the IC initialization code.
-    Handle<Code> stub = ComputeCallInitialize(arg_count);
+    InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+    Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
      CodeForSourcePosition(node->position());
      frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
                             arg_count + 1);
@@ -3102,7 +3107,8 @@
        }

        // Set the receiver register and call the IC initialization code.
-      Handle<Code> stub = ComputeCallInitialize(arg_count);
+      InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+      Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
        CodeForSourcePosition(node->position());
        frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
        __ ldr(cp, frame_->Context());
@@ -3200,7 +3206,8 @@
    // Call the function.
    CodeForSourcePosition(node->position());

-  CallFunctionStub call_function(arg_count);
+  InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+  CallFunctionStub call_function(arg_count, in_loop);
    frame_->CallStub(&call_function, arg_count + 1);

    __ ldr(cp, frame_->Context());
@@ -3462,7 +3469,8 @@

    if (function == NULL) {
      // Call the JS runtime function.
-    Handle<Code> stub = ComputeCallInitialize(arg_count);
+    InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+    Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
      frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
      __ ldr(cp, frame_->Context());
      frame_->Drop();

Modified: branches/bleeding_edge/src/arm/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.h        (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.h        Mon May 25 11:29:02 2009
@@ -206,6 +206,8 @@
    JumpTarget* true_target() const  { return state_->true_target(); }
    JumpTarget* false_target() const  { return state_->false_target(); }

+  // We don't track loop nesting level on ARM yet.
+  int loop_nesting() const { return 0; }

    // Node visitors.
    void VisitStatements(ZoneList<Statement*>* statements);
@@ -318,8 +320,7 @@
    Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

-  Handle<Code> ComputeCallInitialize(int argc);
-  Handle<Code> ComputeCallInitializeInLoop(int argc);
+  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);

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

Modified: branches/bleeding_edge/src/arm/ic-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/ic-arm.cc    (original)
+++ branches/bleeding_edge/src/arm/ic-arm.cc    Mon May 25 11:29:02 2009
@@ -212,7 +212,7 @@

    // Probe the stub cache.
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL,  
argc);
    StubCache::GenerateProbe(masm, flags, r1, r2, r3);

    // If the stub cache probing failed, the receiver might be a value.
@@ -423,7 +423,9 @@

    __ ldr(r0, MemOperand(sp, 0));
    // Probe the stub cache.
-  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
+                                         NOT_IN_LOOP,
+                                         MONOMORPHIC);
    StubCache::GenerateProbe(masm, flags, r0, r2, r3);

    // Cache miss: Jump to runtime.
@@ -756,7 +758,9 @@

    // Get the receiver from the stack and probe the stub cache.
    __ ldr(r1, MemOperand(sp));
-  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
+                                         NOT_IN_LOOP,
+                                         MONOMORPHIC);
    StubCache::GenerateProbe(masm, flags, r1, r2, r3);

    // Cache miss: Jump to runtime.

Modified: branches/bleeding_edge/src/arm/stub-cache-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/stub-cache-arm.cc    (original)
+++ branches/bleeding_edge/src/arm/stub-cache-arm.cc    Mon May 25 11:29:02  
2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -62,7 +62,7 @@

    // Check that the flags match what we're looking for.
    __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
-  __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
+  __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
    __ cmp(offset, Operand(flags));
    __ b(ne, &miss);

@@ -495,7 +495,9 @@
  Object* CallStubCompiler::CompileCallField(Object* object,
                                             JSObject* holder,
                                             int index,
-                                           String* name) {
+                                           String* name,
+                                           Code::Flags flags) {
+  ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
    // ----------- S t a t e -------------
    //  -- lr: return address
    // -----------------------------------
@@ -539,14 +541,16 @@
    __ Jump(ic, RelocInfo::CODE_TARGET);

    // Return the generated code.
-  return GetCode(FIELD, name);
+  return GetCodeWithFlags(flags, name);
  }


  Object* CallStubCompiler::CompileCallConstant(Object* object,
                                                JSObject* holder,
                                                JSFunction* function,
-                                              CheckType check) {
+                                              CheckType check,
+                                              Code::Flags flags) {
+  ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
    // ----------- S t a t e -------------
    //  -- lr: return address
    // -----------------------------------
@@ -664,7 +668,7 @@
    if (function->shared()->name()->IsString()) {
      function_name = String::cast(function->shared()->name());
    }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCodeWithFlags(flags, function_name);
  }



Modified: branches/bleeding_edge/src/builtins.cc
==============================================================================
--- branches/bleeding_edge/src/builtins.cc      (original)
+++ branches/bleeding_edge/src/builtins.cc      Mon May 25 11:29:02 2009
@@ -666,12 +666,12 @@
        Code::ComputeFlags(Code::BUILTIN)  \
      },

-#define DEF_FUNCTION_PTR_A(name, kind, state) \
-    { FUNCTION_ADDR(Generate_##name),         \
-      NULL,                                   \
-      #name,                                  \
-      name,                                   \
-      Code::ComputeFlags(Code::kind, state)   \
+#define DEF_FUNCTION_PTR_A(name, kind, state)              \
+    { FUNCTION_ADDR(Generate_##name),                      \
+      NULL,                                                \
+      #name,                                               \
+      name,                                                \
+      Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state)   \
      },

    // Define array of pointers to generators and C builtin functions.

Modified: branches/bleeding_edge/src/code-stubs.cc
==============================================================================
--- branches/bleeding_edge/src/code-stubs.cc    (original)
+++ branches/bleeding_edge/src/code-stubs.cc    Mon May 25 11:29:02 2009
@@ -59,7 +59,7 @@
      masm.GetCode(&desc);

      // Copy the generated code into a heap object, and store the major key.
-    Code::Flags flags = Code::ComputeFlags(Code::STUB);
+    Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop());
      Handle<Code> code = Factory::NewCode(desc, NULL, flags,  
masm.CodeObject());
      code->set_major_key(MajorKey());


Modified: branches/bleeding_edge/src/code-stubs.h
==============================================================================
--- branches/bleeding_edge/src/code-stubs.h     (original)
+++ branches/bleeding_edge/src/code-stubs.h     Mon May 25 11:29:02 2009
@@ -83,6 +83,10 @@
    virtual Major MajorKey() = 0;
    virtual int MinorKey() = 0;

+  // The CallFunctionStub needs to override this so it can encode whether a
+  // lazily generated function should be fully optimized or not.
+  virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
+
    // Returns a name for logging/debugging purposes.
    virtual const char* GetName() { return MajorName(MajorKey()); }


Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc       (original)
+++ branches/bleeding_edge/src/codegen.cc       Mon May 25 11:29:02 2009
@@ -171,7 +171,8 @@
    CodeDesc desc;
    cgen.masm()->GetCode(&desc);
    ZoneScopeInfo sinfo(flit->scope());
-  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
+  InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
+  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
    Handle<Code> code = Factory::NewCode(desc,
                                         &sinfo,
                                         flags,
@@ -323,17 +324,18 @@
  }


-Handle<Code> CodeGenerator::ComputeCallInitialize(int argc) {
-  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc), Code);
-}
-
-
-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);
+Handle<Code> CodeGenerator::ComputeCallInitialize(
+    int argc,
+    InLoopFlag in_loop) {
+  if (in_loop == IN_LOOP) {
+    // Force the creation of the corresponding stub outside loops,
+    // because it may be used when clearing the ICs later - it is
+    // possible for a series of IC transitions to lose the in-loop
+    // information, and the IC clearing code can't generate a stub
+    // that it needs so we need to ensure it is generated already.
+    ComputeCallInitialize(argc, NOT_IN_LOOP);
+  }
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc, in_loop),  
Code);
  }



Modified: branches/bleeding_edge/src/globals.h
==============================================================================
--- branches/bleeding_edge/src/globals.h        (original)
+++ branches/bleeding_edge/src/globals.h        Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -326,8 +326,6 @@
  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.
@@ -339,6 +337,12 @@
    // Special states for debug break or step in prepare stubs.
    DEBUG_BREAK,
    DEBUG_PREPARE_STEP_IN
+};
+
+
+enum InLoopFlag {
+  NOT_IN_LOOP,
+  IN_LOOP
  };



Modified: branches/bleeding_edge/src/ia32/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/codegen-ia32.cc     (original)
+++ branches/bleeding_edge/src/ia32/codegen-ia32.cc     Mon May 25 11:29:02 2009
@@ -1653,12 +1653,14 @@

  class CallFunctionStub: public CodeStub {
   public:
-  explicit CallFunctionStub(int argc) : argc_(argc) { }
+  CallFunctionStub(int argc, InLoopFlag in_loop)
+      : argc_(argc), in_loop_(in_loop) { }

    void Generate(MacroAssembler* masm);

   private:
    int argc_;
+  InLoopFlag in_loop_;

  #ifdef DEBUG
    void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
@@ -1666,6 +1668,7 @@

    Major MajorKey() { return CallFunction; }
    int MinorKey() { return argc_; }
+  InLoopFlag InLoop() { return in_loop_; }
  };


@@ -1683,7 +1686,8 @@
    CodeForSourcePosition(position);

    // Use the shared code stub to call the function.
-  CallFunctionStub call_function(arg_count);
+  InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+  CallFunctionStub call_function(arg_count, in_loop);
    Result answer = frame_->CallStub(&call_function, arg_count + 1);
    // Restore context and replace function on the stack with the
    // result of the stub invocation.
@@ -4217,7 +4221,8 @@

    // Call the function.
    CodeForSourcePosition(node->position());
-  CallFunctionStub call_function(arg_count);
+  InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+  CallFunctionStub call_function(arg_count, in_loop);
    result = frame_->CallStub(&call_function, arg_count + 1);

    // Restore the context and overwrite the function on the stack with
@@ -4581,9 +4586,10 @@
    }

    if (function == NULL) {
-    // Call the JS runtime function.  Pass 0 as the loop nesting depth
-    // because we do not handle runtime calls specially in loops.
-    Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count,  
0);
+    // Call the JS runtime function.
+    Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET,
+                                       arg_count,
+                                       loop_nesting_);
      frame_->RestoreContextRegister();
      frame_->SetElementAt(0, &answer);
    } else {
@@ -5395,9 +5401,13 @@
        bool is_global = var != NULL;
        ASSERT(!is_global || var->is_global());

-      if (is_global || cgen_->scope()->is_global_scope()) {
-        // Do not inline the inobject property case for loads from the
-        // global object or loads in toplevel code.
+      // Do not inline the inobject property case for loads from the global
+      // object.  Also do not inline for unoptimized code.  This saves time
+      // in the code generator.  Unoptimized code is toplevel code or code
+      // that is not in a loop.
+      if (is_global ||
+          cgen_->scope()->is_global_scope() ||
+          cgen_->loop_nesting() == 0) {
          Comment cmnt(masm, "[ Load from named Property");
          cgen_->frame()->Push(GetName());


Modified: branches/bleeding_edge/src/ia32/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/ia32/codegen-ia32.h      (original)
+++ branches/bleeding_edge/src/ia32/codegen-ia32.h      Mon May 25 11:29:02 2009
@@ -348,7 +348,6 @@
    void IncrementLoopNesting() { loop_nesting_++; }
    void DecrementLoopNesting() { loop_nesting_--; }

-
    // Node visitors.
    void VisitStatements(ZoneList<Statement*>* statements);

@@ -488,8 +487,7 @@
    Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

-  Handle<Code> ComputeCallInitialize(int argc);
-  Handle<Code> ComputeCallInitializeInLoop(int argc);
+  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);

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

Modified: branches/bleeding_edge/src/ia32/ic-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/ic-ia32.cc  (original)
+++ branches/bleeding_edge/src/ia32/ic-ia32.cc  Mon May 25 11:29:02 2009
@@ -427,7 +427,7 @@

    // Probe the stub cache.
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL,  
argc);
    StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);

    // If the stub cache probing failed, the receiver might be a value.
@@ -636,7 +636,9 @@
    __ mov(eax, Operand(esp, kPointerSize));

    // Probe the stub cache.
-  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
+                                         NOT_IN_LOOP,
+                                         MONOMORPHIC);
    StubCache::GenerateProbe(masm, flags, eax, ecx, ebx);

    // Cache miss: Jump to runtime.
@@ -839,7 +841,9 @@

    // Get the receiver from the stack and probe the stub cache.
    __ mov(edx, Operand(esp, 4));
-  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
+                                         NOT_IN_LOOP,
+                                         MONOMORPHIC);
    StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);

    // Cache miss: Jump to runtime.

Modified: branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  (original)
+++ branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  Mon May 25 11:29:02  
2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -59,7 +59,7 @@

    // Check that the flags match what we're looking for.
    __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
-  __ and_(offset, ~Code::kFlagsTypeMask);
+  __ and_(offset, ~Code::kFlagsNotUsedInLookup);
    __ cmp(offset, flags);
    __ j(not_equal, &miss);

@@ -471,7 +471,9 @@
  Object* CallStubCompiler::CompileCallField(Object* object,
                                             JSObject* holder,
                                             int index,
-                                           String* name) {
+                                           String* name,
+                                           Code::Flags flags) {
+  ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
    // ----------- S t a t e -------------
    // -----------------------------------
    Label miss;
@@ -512,14 +514,16 @@
    __ jmp(ic, RelocInfo::CODE_TARGET);

    // Return the generated code.
-  return GetCode(FIELD, name);
+  return GetCodeWithFlags(flags, name);
  }


  Object* CallStubCompiler::CompileCallConstant(Object* object,
                                                JSObject* holder,
                                                JSFunction* function,
-                                              CheckType check) {
+                                              CheckType check,
+                                              Code::Flags flags) {
+  ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
    // ----------- S t a t e -------------
    // -----------------------------------
    Label miss;
@@ -634,7 +638,7 @@
    if (function->shared()->name()->IsString()) {
      function_name = String::cast(function->shared()->name());
    }
-  return GetCode(CONSTANT_FUNCTION, function_name);
+  return GetCodeWithFlags(flags, function_name);
  }



Modified: branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc       (original)
+++ branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc       Mon May 25  
11:29:02 2009
@@ -941,9 +941,8 @@
    // Arguments, receiver, and function name are on top of the frame.
    // The IC expects them on the stack.  It does not drop the function
    // name slot (but it does drop the rest).
-  Handle<Code> ic = (loop_nesting > 0)
-      ? cgen()->ComputeCallInitializeInLoop(arg_count)
-      : cgen()->ComputeCallInitialize(arg_count);
+  InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
+  Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, in_loop);
    // Spill args, receiver, and function.  The call will drop args and
    // receiver.
    PrepareForCall(arg_count + 2, arg_count + 1);

Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc    (original)
+++ branches/bleeding_edge/src/ic.cc    Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -39,10 +39,9 @@
  namespace internal {

  #ifdef DEBUG
-static char TransitionMarkFromState(IC::State state) {
+static const char TransitionMarkFromState(IC::State state) {
    switch (state) {
      case UNINITIALIZED: return '0';
-    case UNINITIALIZED_IN_LOOP: return 'L';
      case PREMONOMORPHIC: return 'P';
      case MONOMORPHIC: return '1';
      case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -61,12 +60,14 @@
  void IC::TraceIC(const char* type,
                   Handle<String> name,
                   State old_state,
-                 Code* new_target) {
+                 Code* new_target,
+                 const char* extra_info) {
    if (FLAG_trace_ic) {
      State new_state = StateFrom(new_target, Heap::undefined_value());
-    PrintF("[%s (%c->%c) ", type,
+    PrintF("[%s (%c->%c)%s", type,
             TransitionMarkFromState(old_state),
-           TransitionMarkFromState(new_state));
+           TransitionMarkFromState(new_state),
+           extra_info);
      name->Print();
      PrintF("]\n");
    }
@@ -227,8 +228,10 @@

  void CallIC::Clear(Address address, Code* target) {
    State state = target->ic_state();
-  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
-  Code* code = StubCache::FindCallInitialize(target->arguments_count());
+  InLoopFlag in_loop = target->ic_in_loop();
+  if (state == UNINITIALIZED) return;
+  Code* code =
+      StubCache::FindCallInitialize(target->arguments_count(), in_loop);
    SetTargetAtAddress(address, code);
  }

@@ -391,21 +394,22 @@

    // Compute the number of arguments.
    int argc = target()->arguments_count();
+  InLoopFlag in_loop = target()->ic_in_loop();
    Object* code = NULL;

    if (state == UNINITIALIZED) {
      // This is the first time we execute this inline cache.
      // Set the target to the pre monomorphic stub to delay
      // setting the monomorphic state.
-    code = StubCache::ComputeCallPreMonomorphic(argc);
+    code = StubCache::ComputeCallPreMonomorphic(argc, in_loop);
    } else if (state == MONOMORPHIC) {
-    code = StubCache::ComputeCallMegamorphic(argc);
+    code = StubCache::ComputeCallMegamorphic(argc, in_loop);
    } else {
      // Compute monomorphic stub.
      switch (lookup->type()) {
        case FIELD: {
          int index = lookup->GetFieldIndex();
-        code = StubCache::ComputeCallField(argc, *name, *object,
+        code = StubCache::ComputeCallField(argc, in_loop, *name, *object,
                                             lookup->holder(), index);
          break;
        }
@@ -414,7 +418,7 @@
          // call; used for rewriting to monomorphic state and making sure
          // that the code stub is in the stub cache.
          JSFunction* function = lookup->GetConstantFunction();
-        code = StubCache::ComputeCallConstant(argc, *name, *object,
+        code = StubCache::ComputeCallConstant(argc, in_loop, *name,  
*object,
                                                lookup->holder(), function);
          break;
        }
@@ -426,7 +430,7 @@
          if (!object->IsJSObject()) return;
          Handle<JSObject> receiver = Handle<JSObject>::cast(object);
          if (lookup->holder() != *receiver) return;
-        code = StubCache::ComputeCallNormal(argc, *name, *receiver);
+        code = StubCache::ComputeCallNormal(argc, in_loop, *name,  
*receiver);
          break;
        }
        case INTERCEPTOR: {
@@ -444,14 +448,15 @@
    if (code->IsFailure()) return;

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

  #ifdef DEBUG
-  TraceIC("CallIC", name, state, target());
+  TraceIC("CallIC", name, state, target(), in_loop ? " (in-loop)" : "");
  #endif
  }

@@ -1089,14 +1094,27 @@
    IC::State state = IC::StateFrom(ic.target(), args[0]);
    Object* result =
        ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
-  if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+
+  // The first time the inline cache is updated may be the first time the
+  // function it references gets called.  If the function was lazily  
compiled
+  // then the first call will trigger a compilation.  We check for this  
case
+  // and we do the compilation immediately, instead of waiting for the stub
+  // currently attached to the JSFunction object to trigger compilation.   
We
+  // do this in the case where we know that the inline cache is inside a  
loop,
+  // because then we know that we want to optimize the function.
+  if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
      return result;
+  }

-  // Compile the function with the knowledge that it's called from
-  // within a loop. This enables further optimization of the function.
+  // Compile now with optimization.
    HandleScope scope;
    Handle<JSFunction> function =  
Handle<JSFunction>(JSFunction::cast(result));
-  if (!function->is_compiled()) CompileLazyInLoop(function,  
CLEAR_EXCEPTION);
+  InLoopFlag in_loop = ic.target()->ic_in_loop();
+  if (in_loop == IN_LOOP) {
+    CompileLazyInLoop(function, CLEAR_EXCEPTION);
+  } else {
+    CompileLazy(function, CLEAR_EXCEPTION);
+  }
    return *function;
  }


Modified: branches/bleeding_edge/src/ic.h
==============================================================================
--- branches/bleeding_edge/src/ic.h     (original)
+++ branches/bleeding_edge/src/ic.h     Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -121,7 +121,8 @@
    static void TraceIC(const char* type,
                        Handle<String> name,
                        State old_state,
-                      Code* new_target);
+                      Code* new_target,
+                      const char* extra_info = "");
  #endif

    static Failure* TypeError(const char* type,

Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h    (original)
+++ branches/bleeding_edge/src/objects-inl.h    Mon May 25 11:29:02 2009
@@ -1898,6 +1898,11 @@
  }


+InLoopFlag Code::ic_in_loop() {
+  return ExtractICInLoopFromFlags(flags());
+}
+
+
  InlineCacheState Code::ic_state() {
    InlineCacheState result = ExtractICStateFromFlags(flags());
    // Only allow uninitialized or debugger states for non-IC code
@@ -1944,11 +1949,13 @@


  Code::Flags Code::ComputeFlags(Kind kind,
+                               InLoopFlag in_loop,
                                 InlineCacheState ic_state,
                                 PropertyType type,
                                 int argc) {
    // Compute the bit mask.
    int bits = kind << kFlagsKindShift;
+  if (in_loop) bits |= kFlagsICInLoopMask;
    bits |= ic_state << kFlagsICStateShift;
    bits |= type << kFlagsTypeShift;
    bits |= argc << kFlagsArgumentsCountShift;
@@ -1956,6 +1963,7 @@
    Flags result = static_cast<Flags>(bits);
    ASSERT(ExtractKindFromFlags(result) == kind);
    ASSERT(ExtractICStateFromFlags(result) == ic_state);
+  ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
    ASSERT(ExtractTypeFromFlags(result) == type);
    ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
    return result;
@@ -1964,8 +1972,9 @@

  Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
                                            PropertyType type,
+                                          InLoopFlag in_loop,
                                            int argc) {
-  return ComputeFlags(kind, MONOMORPHIC, type, argc);
+  return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
  }


@@ -1978,6 +1987,12 @@
  InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
    int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
    return static_cast<InlineCacheState>(bits);
+}
+
+
+InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
+  int bits = (flags & kFlagsICInLoopMask);
+  return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
  }



Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Mon May 25 11:29:02 2009
@@ -4860,7 +4860,6 @@
  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/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -2253,9 +2253,10 @@

    // [flags]: Access to specific code flags.
    inline Kind kind();
-  inline InlineCacheState ic_state();  // only valid for IC stubs
-  inline PropertyType type();  // only valid for monomorphic IC stubs
-  inline int arguments_count();  // only valid for call IC stubs
+  inline InlineCacheState ic_state();  // Only valid for IC stubs.
+  inline InLoopFlag ic_in_loop();  // Only valid for IC stubs..
+  inline PropertyType type();  // Only valid for monomorphic IC stubs.
+  inline int arguments_count();  // Only valid for call IC stubs.

    // Testers for IC stub kinds.
    inline bool is_inline_cache_stub();
@@ -2277,16 +2278,20 @@

    // Flags operations.
    static inline Flags ComputeFlags(Kind kind,
+                                   InLoopFlag in_loop = NOT_IN_LOOP,
                                     InlineCacheState ic_state =  
UNINITIALIZED,
                                     PropertyType type = NORMAL,
                                     int argc = -1);

-  static inline Flags ComputeMonomorphicFlags(Kind kind,
-                                              PropertyType type,
-                                              int argc = -1);
+  static inline Flags ComputeMonomorphicFlags(
+      Kind kind,
+      PropertyType type,
+      InLoopFlag in_loop = NOT_IN_LOOP,
+      int argc = -1);

    static inline Kind ExtractKindFromFlags(Flags flags);
    static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
+  static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
    static inline PropertyType ExtractTypeFromFlags(Flags flags);
    static inline int ExtractArgumentsCountFromFlags(Flags flags);
    static inline Flags RemoveTypeFromFlags(Flags flags);
@@ -2378,14 +2383,19 @@

    // Flags layout.
    static const int kFlagsICStateShift        = 0;
-  static const int kFlagsKindShift           = 3;
-  static const int kFlagsTypeShift           = 6;
-  static const int kFlagsArgumentsCountShift = 9;
-
-  static const int kFlagsICStateMask        = 0x00000007;  // 000000111
-  static const int kFlagsKindMask           = 0x00000038;  // 000111000
-  static const int kFlagsTypeMask           = 0x000001C0;  // 111000000
-  static const int kFlagsArgumentsCountMask = 0xFFFFFE00;
+  static const int kFlagsICInLoopShift       = 3;
+  static const int kFlagsKindShift           = 4;
+  static const int kFlagsTypeShift           = 7;
+  static const int kFlagsArgumentsCountShift = 10;
+
+  static const int kFlagsICStateMask        = 0x00000007;  // 0000000111
+  static const int kFlagsICInLoopMask       = 0x00000008;  // 0000001000
+  static const int kFlagsKindMask           = 0x00000070;  // 0001110000
+  static const int kFlagsTypeMask           = 0x00000380;  // 1110000000
+  static const int kFlagsArgumentsCountMask = 0xFFFFFC00;
+
+  static const int kFlagsNotUsedInLookup =
+      (kFlagsICInLoopMask | kFlagsTypeMask);

   private:
    DISALLOW_IMPLICIT_CONSTRUCTORS(Code);

Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc       (original)
+++ branches/bleeding_edge/src/runtime.cc       Mon May 25 11:29:02 2009
@@ -4319,9 +4319,15 @@
    }
  #endif

-  // Compile the target function.
+  // Compile the target function.  Here we compile using CompileLazyInLoop  
in
+  // order to get the optimized version.  This helps code like delta-blue
+  // that calls performance-critical routines through constructors.  A
+  // constructor call doesn't use a CallIC, it uses a LoadIC followed by a
+  // direct call.  Since the in-loop tracking takes place through CallICs
+  // this means that things called through constructors are never known to
+  // be in loops.  We compile them as if they are in loops here just in  
case.
    ASSERT(!function->is_compiled());
-  if (!CompileLazy(function, KEEP_EXCEPTION)) {
+  if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
      return Failure::Exception();
    }


Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc    (original)
+++ branches/bleeding_edge/src/stub-cache.cc    Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
@@ -370,6 +370,7 @@


  Object* StubCache::ComputeCallConstant(int argc,
+                                       InLoopFlag in_loop,
                                         String* name,
                                         Object* object,
                                         JSObject* holder,
@@ -388,7 +389,10 @@
    }

    Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::CALL_IC, CONSTANT_FUNCTION,  
argc);
+      Code::ComputeMonomorphicFlags(Code::CALL_IC,
+                                    CONSTANT_FUNCTION,
+                                    in_loop,
+                                    argc);
    Object* code = map->FindInCodeCache(name, flags);
    if (code->IsUndefined()) {
      if (object->IsJSObject()) {
@@ -406,7 +410,7 @@
      if (!function->is_compiled()) return Failure::InternalError();
      // Compile the stub - only create stubs for fully compiled functions.
      CallStubCompiler compiler(argc);
-    code = compiler.CompileCallConstant(object, holder, function, check);
+    code = compiler.CompileCallConstant(object, holder, function, check,  
flags);
      if (code->IsFailure()) return code;
      LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
      Object* result = map->UpdateCodeCache(name, Code::cast(code));
@@ -417,6 +421,7 @@


  Object* StubCache::ComputeCallField(int argc,
+                                    InLoopFlag in_loop,
                                      String* name,
                                      Object* object,
                                      JSObject* holder,
@@ -431,11 +436,14 @@
      object = holder;
    }

-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, FIELD,  
argc);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
+                                                    FIELD,
+                                                    in_loop,
+                                                    argc);
    Object* code = map->FindInCodeCache(name, flags);
    if (code->IsUndefined()) {
      CallStubCompiler compiler(argc);
-    code = compiler.CompileCallField(object, holder, index, name);
+    code = compiler.CompileCallField(object, holder, index, name, flags);
      if (code->IsFailure()) return code;
      LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
      Object* result = map->UpdateCodeCache(name, Code::cast(code));
@@ -461,7 +469,10 @@
    }

    Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::CALL_IC, INTERCEPTOR, argc);
+      Code::ComputeMonomorphicFlags(Code::CALL_IC,
+                                    INTERCEPTOR,
+                                    NOT_IN_LOOP,
+                                    argc);
    Object* code = map->FindInCodeCache(name, flags);
    if (code->IsUndefined()) {
      CallStubCompiler compiler(argc);
@@ -476,9 +487,10 @@


  Object* StubCache::ComputeCallNormal(int argc,
+                                     InLoopFlag in_loop,
                                       String* name,
                                       JSObject* receiver) {
-  Object* code = ComputeCallNormal(argc);
+  Object* code = ComputeCallNormal(argc, in_loop);
    if (code->IsFailure()) return code;
    return Set(name, receiver->map(), Code::cast(code));
  }
@@ -523,9 +535,9 @@
  }


-Code* StubCache::FindCallInitialize(int argc) {
+Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL,  
argc);
    Object* result = ProbeCache(flags);
    ASSERT(!result->IsUndefined());
    // This might be called during the marking phase of the collector
@@ -534,9 +546,9 @@
  }


-Object* StubCache::ComputeCallInitialize(int argc) {
+Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -544,20 +556,9 @@
  }


-Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop)  
{
    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);
+      Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -565,9 +566,9 @@
  }


-Object* StubCache::ComputeCallNormal(int argc) {
+Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -575,9 +576,9 @@
  }


-Object* StubCache::ComputeCallMegamorphic(int argc) {
+Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, MEGAMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -587,7 +588,7 @@

  Object* StubCache::ComputeCallMiss(int argc) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::STUB, MEGAMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -598,7 +599,7 @@
  #ifdef ENABLE_DEBUGGER_SUPPORT
  Object* StubCache::ComputeCallDebugBreak(int argc) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
+      Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -608,7 +609,11 @@

  Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, DEBUG_PREPARE_STEP_IN, NORMAL,  
argc);
+      Code::ComputeFlags(Code::CALL_IC,
+                         NOT_IN_LOOP,
+                         DEBUG_PREPARE_STEP_IN,
+                         NORMAL,
+                         argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -619,7 +624,7 @@

  Object* StubCache::ComputeLazyCompile(int argc) {
    Code::Flags flags =
-      Code::ComputeFlags(Code::STUB, UNINITIALIZED, NORMAL, argc);
+      Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, UNINITIALIZED, NORMAL,  
argc);
    Object* probe = ProbeCache(flags);
    if (!probe->IsUndefined()) return probe;
    StubCompiler compiler;
@@ -918,7 +923,10 @@

  Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
    int argc = arguments_.immediate();
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, type,  
argc);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
+                                                    type,
+                                                    NOT_IN_LOOP,
+                                                    argc);
    return GetCodeWithFlags(flags, name);
  }


Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h     (original)
+++ branches/bleeding_edge/src/stub-cache.h     Mon May 25 11:29:02 2009
@@ -128,18 +128,23 @@
    // ---

    static Object* ComputeCallField(int argc,
+                                  InLoopFlag in_loop,
                                    String* name,
                                    Object* object,
                                    JSObject* holder,
                                    int index);

    static Object* ComputeCallConstant(int argc,
+                                     InLoopFlag in_loop,
                                       String* name,
                                       Object* object,
                                       JSObject* holder,
                                       JSFunction* function);

-  static Object* ComputeCallNormal(int argc, String* name, JSObject*  
receiver);
+  static Object* ComputeCallNormal(int argc,
+                                   InLoopFlag in_loop,
+                                   String* name,
+                                   JSObject* receiver);

    static Object* ComputeCallInterceptor(int argc,
                                          String* name,
@@ -148,15 +153,14 @@

    // ---

-  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);
+  static Object* ComputeCallInitialize(int argc, InLoopFlag in_loop);
+  static Object* ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop);
+  static Object* ComputeCallNormal(int argc, InLoopFlag in_loop);
+  static Object* ComputeCallMegamorphic(int argc, InLoopFlag in_loop);
    static Object* ComputeCallMiss(int argc);

    // Finds the Code object stored in the Heap::non_monomorphic_cache().
-  static Code* FindCallInitialize(int argc);
+  static Code* FindCallInitialize(int argc, InLoopFlag in_loop);

  #ifdef ENABLE_DEBUGGER_SUPPORT
    static Object* ComputeCallDebugBreak(int argc);
@@ -209,8 +213,12 @@
      // 4Gb (and not at all if it isn't).
      uint32_t map_low32bits =
          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
+    // We always set the in_loop bit to zero when generating the lookup  
code
+    // so do it here too so the hash codes match.
+    uint32_t iflags =
+        (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
      // Base the offset on a simple combination of name, flags, and map.
-    uint32_t key = (map_low32bits + field) ^ flags;
+    uint32_t key = (map_low32bits + field) ^ iflags;
      return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
    }

@@ -218,7 +226,11 @@
      // Use the seed from the primary cache in the secondary cache.
      uint32_t string_low32bits =
          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
-    uint32_t key = seed - string_low32bits + flags;
+    // We always set the in_loop bit to zero when generating the lookup  
code
+    // so do it here too so the hash codes match.
+    uint32_t iflags =
+        (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
+    uint32_t key = seed - string_low32bits + iflags;
      return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
    }

@@ -469,11 +481,13 @@
    Object* CompileCallField(Object* object,
                             JSObject* holder,
                             int index,
-                           String* name);
+                           String* name,
+                           Code::Flags flags);
    Object* CompileCallConstant(Object* object,
                                JSObject* holder,
                                JSFunction* function,
-                              CheckType check);
+                              CheckType check,
+                              Code::Flags flags);
    Object* CompileCallInterceptor(Object* object,
                                   JSObject* holder,
                                   String* name);

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

Reply via email to