Author: [EMAIL PROTECTED]
Date: Fri Oct  3 02:16:12 2008
New Revision: 420

Modified:
    branches/bleeding_edge/src/builtins.cc
    branches/bleeding_edge/src/builtins.h
    branches/bleeding_edge/src/date-delay.js
    branches/bleeding_edge/src/handles.cc
    branches/bleeding_edge/src/ic-arm.cc
    branches/bleeding_edge/src/ic-ia32.cc
    branches/bleeding_edge/src/ic.cc
    branches/bleeding_edge/src/ic.h
    branches/bleeding_edge/src/stub-cache-arm.cc
    branches/bleeding_edge/src/stub-cache-ia32.cc

Log:
- Added fast case for extending the JSObject properties storage.
- Changed date to compute local_time_offset at load time.

Review URL: http://codereview.chromium.org/6441

Modified: branches/bleeding_edge/src/builtins.cc
==============================================================================
--- branches/bleeding_edge/src/builtins.cc      (original)
+++ branches/bleeding_edge/src/builtins.cc      Fri Oct  3 02:16:12 2008
@@ -561,6 +561,10 @@
  }


+static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
+  StoreIC::GenerateExtendStorage(masm);
+}
+
  static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
    StoreIC::GenerateMegamorphic(masm);
  }

Modified: branches/bleeding_edge/src/builtins.h
==============================================================================
--- branches/bleeding_edge/src/builtins.h       (original)
+++ branches/bleeding_edge/src/builtins.h       Fri Oct  3 02:16:12 2008
@@ -62,6 +62,8 @@
    V(StoreIC_Miss,               BUILTIN, UNINITIALIZED)        \
    V(KeyedStoreIC_Miss,          BUILTIN, UNINITIALIZED)        \
                                                                 \
+  V(StoreIC_ExtendStorage,      BUILTIN, UNINITIALIZED)        \
+                                                               \
    V(LoadIC_Initialize,          LOAD_IC, UNINITIALIZED)        \
    V(LoadIC_PreMonomorphic,      LOAD_IC, PREMONOMORPHIC)       \
    V(LoadIC_Normal,              LOAD_IC, MONOMORPHIC)          \

Modified: branches/bleeding_edge/src/date-delay.js
==============================================================================
--- branches/bleeding_edge/src/date-delay.js    (original)
+++ branches/bleeding_edge/src/date-delay.js    Fri Oct  3 02:16:12 2008
@@ -36,7 +36,6 @@
  // changes to these properties.
  const $Date = global.Date;

-
  // ECMA 262 - 15.9.1.2
  function Day(time) {
    return $floor(time/msPerDay);
@@ -127,17 +126,6 @@
    return TimeClip(MakeDate(day, TimeWithinDay(t)));
  }

-
-var local_time_offset;
-
-function LocalTimeOffset() {
-  if (IS_UNDEFINED(local_time_offset)) {
-    local_time_offset = %DateLocalTimeOffset();
-  }
-  return local_time_offset;
-}
-
-
  var daylight_cache_time = $NaN;
  var daylight_cache_offset;

@@ -170,16 +158,17 @@
    return Modulo(Day(time) + 4, 7);
  }

+var local_time_offset = %DateLocalTimeOffset();

  function LocalTime(time) {
    if ($isNaN(time)) return time;
-  return time + LocalTimeOffset() + DaylightSavingsOffset(time);
+  return time + local_time_offset + DaylightSavingsOffset(time);
  }


  function UTC(time) {
    if ($isNaN(time)) return time;
-  var tmp = time - LocalTimeOffset();
+  var tmp = time - local_time_offset;
    return tmp - DaylightSavingsOffset(tmp);
  }

@@ -530,7 +519,7 @@


  function LocalTimezoneString(time) {
-  var timezoneOffset = (LocalTimeOffset() + DaylightSavingsOffset(time)) /  
msPerMinute;
+  var timezoneOffset = (local_time_offset + DaylightSavingsOffset(time)) /  
msPerMinute;
    var sign = (timezoneOffset >= 0) ? 1 : -1;
    var hours = $floor((sign * timezoneOffset)/60);
    var min   = $floor((sign * timezoneOffset)%60);

Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc       (original)
+++ branches/bleeding_edge/src/handles.cc       Fri Oct  3 02:16:12 2008
@@ -86,21 +86,26 @@
  }


-void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo>  
shared,
-                                          int estimate) {
+static int ExpectedNofPropertiesFromEstimate(int estimate) {
    // TODO(1231235): We need dynamic feedback to estimate the number
    // of expected properties in an object. The static hack below
    // is barely a solution.
-  shared->set_expected_nof_properties(estimate + 2);
+  if (estimate == 0) return 4;
+  return estimate + 2;
+}
+
+
+void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo>  
shared,
+                                          int estimate) {
+  shared->set_expected_nof_properties(
+      ExpectedNofPropertiesFromEstimate(estimate));
  }


  void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
                                            int estimate) {
-  // TODO(1231235): We need dynamic feedback to estimate the number
-  // of expected properties in an object. The static hack below
-  // is barely a solution.
-  SetExpectedNofProperties(func, estimate + 2);
+  SetExpectedNofProperties(
+      func, ExpectedNofPropertiesFromEstimate(estimate));
  }



Modified: branches/bleeding_edge/src/ic-arm.cc
==============================================================================
--- branches/bleeding_edge/src/ic-arm.cc        (original)
+++ branches/bleeding_edge/src/ic-arm.cc        Fri Oct  3 02:16:12 2008
@@ -539,9 +539,6 @@
  }


-// Defined in ic.cc.
-Object* StoreIC_Miss(Arguments args);
-
  void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
    // ----------- S t a t e -------------
    //  -- r0    : value
@@ -557,6 +554,22 @@

    // Cache miss: Jump to runtime.
    Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+
+  __ ldr(r3, MemOperand(sp));  // copy receiver
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __  
TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ExtendStorage)), 3);
  }



Modified: branches/bleeding_edge/src/ic-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ic-ia32.cc       (original)
+++ branches/bleeding_edge/src/ic-ia32.cc       Fri Oct  3 02:16:12 2008
@@ -669,9 +669,6 @@
  }


-// Defined in ic.cc.
-Object* StoreIC_Miss(Arguments args);
-
  void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
    // ----------- S t a t e -------------
    //  -- eax    : value
@@ -687,6 +684,25 @@

    // Cache miss: Jump to runtime.
    Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
+}
+
+
+void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : transition map
+  //  -- esp[0] : return address
+  //  -- esp[4] : receiver
+  // -----------------------------------
+
+  // Move the return address below the arguments.
+  __ pop(ebx);
+  __ push(Operand(esp, 0));
+  __ push(ecx);
+  __ push(eax);
+  __ push(ebx);
+  // Perform tail call to the entry.
+  __  
TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ExtendStorage)), 3);
  }



Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc    (original)
+++ branches/bleeding_edge/src/ic.cc    Fri Oct  3 02:16:12 2008
@@ -874,10 +874,8 @@
      }
      case MAP_TRANSITION: {
        if (lookup->GetAttributes() != NONE) return;
-      if (receiver->map()->unused_property_fields() == 0) return;
        HandleScope scope;
-      ASSERT(type == MAP_TRANSITION &&
-             (receiver->map()->unused_property_fields() > 0));
+      ASSERT(type == MAP_TRANSITION);
        Handle<Map> transition(lookup->GetTransitionMap());
        int index = transition->PropertyIndexFor(*name);
        code = StubCache::ComputeStoreField(*name, *receiver, index,  
*transition);
@@ -906,7 +904,8 @@
    if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
      set_target(Code::cast(code));
    } else if (state == MONOMORPHIC) {
-    set_target(megamorphic_stub());
+    // Only move to mega morphic if the target changes.
+    if (target() != Code::cast(code)) set_target(megamorphic_stub());
    }

  #ifdef DEBUG
@@ -996,10 +995,8 @@
      }
      case MAP_TRANSITION: {
        if (lookup->GetAttributes() == NONE) {
-        if (receiver->map()->unused_property_fields() == 0) return;
          HandleScope scope;
-        ASSERT(type == MAP_TRANSITION &&
-               (receiver->map()->unused_property_fields() > 0));
+        ASSERT(type == MAP_TRANSITION);
          Handle<Map> transition(lookup->GetTransitionMap());
          int index = transition->PropertyIndexFor(*name);
          code = StubCache::ComputeKeyedStoreField(*name, *receiver,
@@ -1112,6 +1109,40 @@
    IC::State state = IC::StateFrom(ic.target(), args[0]);
    return ic.Store(state, args.at<Object>(0), args.at<String>(1),
                    args.at<Object>(2));
+}
+
+
+// Extend storage is called in a store inline cache when
+// it is necessary to extend the properties array of a
+// JSObject.
+Object* StoreIC_ExtendStorage(Arguments args) {
+  NoHandleAllocation na;
+  ASSERT(args.length() == 3);
+
+  // Convert the parameters
+  JSObject* object = JSObject::cast(args[0]);
+  Map* transition = Map::cast(args[1]);
+  Object* value = args[2];
+
+  // Check the object has run out out property space.
+  ASSERT(object->HasFastProperties());
+  ASSERT(object->map()->unused_property_fields() == 0);
+
+  // Expand the properties array.
+  FixedArray* old_storage = object->properties();
+  int new_unused = transition->unused_property_fields();
+  int new_size = old_storage->length() + new_unused + 1;
+  Object* result = old_storage->CopySize(new_size);
+  if (result->IsFailure()) return result;
+  FixedArray* new_storage = FixedArray::cast(result);
+  new_storage->set(old_storage->length(), value);
+
+  // Set the new property value and do the map tranistion.
+  object->set_properties(new_storage);
+  object->set_map(transition);
+
+  // Return the stored value.
+  return value;
  }



Modified: branches/bleeding_edge/src/ic.h
==============================================================================
--- branches/bleeding_edge/src/ic.h     (original)
+++ branches/bleeding_edge/src/ic.h     Fri Oct  3 02:16:12 2008
@@ -39,6 +39,7 @@
    ICU(KeyedLoadIC_Miss)         \
    ICU(CallIC_Miss)              \
    ICU(StoreIC_Miss)             \
+  ICU(StoreIC_ExtendStorage)    \
    ICU(KeyedStoreIC_Miss)        \
    /* Utilities for IC stubs. */ \
    ICU(LoadCallbackProperty)     \
@@ -294,6 +295,7 @@
    static void GenerateInitialize(MacroAssembler* masm);
    static void GenerateMiss(MacroAssembler* masm);
    static void GenerateMegamorphic(MacroAssembler* masm);
+  static void GenerateExtendStorage(MacroAssembler* masm);

   private:
    static void Generate(MacroAssembler* masm, const ExternalReference& f);

Modified: branches/bleeding_edge/src/stub-cache-arm.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache-arm.cc        (original)
+++ branches/bleeding_edge/src/stub-cache-arm.cc        Fri Oct  3 02:16:12 2008
@@ -416,10 +416,18 @@

    // Perform map transition for the receiver if necessary.
    if (transition != NULL) {
-    // Update the map of the object; no write barrier updating is
-    // needed because the map is never in new space.
-    __ mov(ip, Operand(Handle<Map>(transition)));
-    __ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
+    if (object->map()->unused_property_fields() == 0) {
+      // The properties must be extended before we can store the value.
+      // We jump to a runtime call that extends the propeties array.
+      __ mov(r2, Operand(Handle<Map>(transition)));
+      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
+      __ Jump(ic, RelocInfo::CODE_TARGET);
+    } else {
+      // Update the map of the object; no write barrier updating is
+      // needed because the map is never in new space.
+      __ mov(ip, Operand(Handle<Map>(transition)));
+      __ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
+    }
    }

    // Write to the properties array.

Modified: branches/bleeding_edge/src/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache-ia32.cc       (original)
+++ branches/bleeding_edge/src/stub-cache-ia32.cc       Fri Oct  3 02:16:12 2008
@@ -436,10 +436,18 @@

    // Perform map transition for the receiver if necessary.
    if (transition != NULL) {
-    // Update the map of the object; no write barrier updating is
-    // needed because the map is never in new space.
-    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
-           Immediate(Handle<Map>(transition)));
+    if (object->map()->unused_property_fields() == 0) {
+      // The properties must be extended before we can store the value.
+      // We jump to a runtime call that extends the propeties array.
+      __ mov(Operand(ecx), Immediate(Handle<Map>(transition)));
+      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
+      __ jmp(ic, RelocInfo::CODE_TARGET);
+    } else {
+      // Update the map of the object; no write barrier updating is
+      // needed because the map is never in new space.
+      __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
+             Immediate(Handle<Map>(transition)));
+    }
    }

    // Write to the properties array.

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

Reply via email to