Revision: 3547
Author: [email protected]
Date: Wed Jan  6 23:49:31 2010
Log: Merge r3387, r3390, r3393, r3394, and r3481 to branches/1.3 to avoid
holding on to global objects from the compilation cache and to increase
the number of maps we can hold in map space.
Review URL: http://codereview.chromium.org/523121
http://code.google.com/p/v8/source/detail?r=3547

Added:
 /branches/1.3/test/mjsunit/regress/regress-524.js
Modified:
 /branches/1.3/src/accessors.cc
 /branches/1.3/src/accessors.h
 /branches/1.3/src/bootstrapper.cc
 /branches/1.3/src/compiler.cc
 /branches/1.3/src/factory.cc
 /branches/1.3/src/globals.h
 /branches/1.3/src/heap-inl.h
 /branches/1.3/src/heap.cc
 /branches/1.3/src/heap.h
 /branches/1.3/src/mark-compact.cc
 /branches/1.3/src/messages.js
 /branches/1.3/src/mirror-delay.js
 /branches/1.3/src/objects-debug.cc
 /branches/1.3/src/objects-inl.h
 /branches/1.3/src/objects.h
 /branches/1.3/src/serialize.cc
 /branches/1.3/src/spaces.cc
 /branches/1.3/src/spaces.h
 /branches/1.3/src/version.cc
 /branches/1.3/test/cctest/test-api.cc
 /branches/1.3/test/mjsunit/mjsunit.status

=======================================
--- /dev/null
+++ /branches/1.3/test/mjsunit/regress/regress-524.js Wed Jan 6 23:49:31 2010
@@ -0,0 +1,32 @@
+// Copyright 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:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test allocation of a large number of maps.
+
+var i = 500000
+var a = new Array(i)
+for (var j = 0; j < i; j++) { var o = {}; o.x = 42; delete o.x; a[j] = o; }
=======================================
--- /branches/1.3/src/accessors.cc      Mon Nov 30 03:23:58 2009
+++ /branches/1.3/src/accessors.cc      Wed Jan  6 23:49:31 2010
@@ -349,29 +349,38 @@


 //
-// Accessors::ScriptGetEvalFromFunction
+// Accessors::ScriptGetEvalFromScript
 //


-Object* Accessors::ScriptGetEvalFromFunction(Object* object, void*) {
+Object* Accessors::ScriptGetEvalFromScript(Object* object, void*) {
   Object* script = JSValue::cast(object)->value();
-  return Script::cast(script)->eval_from_function();
+  if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
+    Handle<SharedFunctionInfo> eval_from_shared(
+ SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
+
+    if (eval_from_shared->script()->IsScript()) {
+ Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
+      return *GetScriptWrapper(eval_from_script);
+    }
+  }
+  return Heap::undefined_value();
 }


-const AccessorDescriptor Accessors::ScriptEvalFromFunction = {
-  ScriptGetEvalFromFunction,
+const AccessorDescriptor Accessors::ScriptEvalFromScript = {
+  ScriptGetEvalFromScript,
   IllegalSetter,
   0
 };


 //
-// Accessors::ScriptGetEvalFromPosition
+// Accessors::ScriptGetEvalFromScriptPosition
 //


-Object* Accessors::ScriptGetEvalFromPosition(Object* object, void*) {
+Object* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) {
   HandleScope scope;
   Handle<Script> script(Script::cast(JSValue::cast(object)->value()));

@@ -383,14 +392,42 @@

// Get the function from where eval was called and find the source position
   // from the instruction offset.
- Handle<Code> code(JSFunction::cast(script->eval_from_function())->code());
+  Handle<Code> code(SharedFunctionInfo::cast(
+      script->eval_from_shared())->code());
   return Smi::FromInt(code->SourcePosition(code->instruction_start() +
                       script->eval_from_instructions_offset()->value()));
 }


-const AccessorDescriptor Accessors::ScriptEvalFromPosition = {
-  ScriptGetEvalFromPosition,
+const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
+  ScriptGetEvalFromScriptPosition,
+  IllegalSetter,
+  0
+};
+
+
+//
+// Accessors::ScriptGetEvalFromFunctionName
+//
+
+
+Object* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) {
+  Object* script = JSValue::cast(object)->value();
+  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
+      Script::cast(script)->eval_from_shared()));
+
+
+  // Find the name of the function calling eval.
+  if (!shared->name()->IsUndefined()) {
+    return shared->name();
+  } else {
+    return shared->inferred_name();
+  }
+}
+
+
+const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
+  ScriptGetEvalFromFunctionName,
   IllegalSetter,
   0
 };
=======================================
--- /branches/1.3/src/accessors.h       Mon Jun  8 05:21:35 2009
+++ /branches/1.3/src/accessors.h       Wed Jan  6 23:49:31 2010
@@ -51,8 +51,9 @@
   V(ScriptCompilationType)          \
   V(ScriptLineEnds)                 \
   V(ScriptContextData)              \
-  V(ScriptEvalFromFunction)         \
-  V(ScriptEvalFromPosition)         \
+  V(ScriptEvalFromScript)           \
+  V(ScriptEvalFromScriptPosition)   \
+  V(ScriptEvalFromFunctionName)     \
   V(ObjectPrototype)

 // Accessors contains all predefined proxy accessors.
@@ -95,8 +96,9 @@
   static Object* ScriptGetCompilationType(Object* object, void*);
   static Object* ScriptGetLineEnds(Object* object, void*);
   static Object* ScriptGetContextData(Object* object, void*);
-  static Object* ScriptGetEvalFromFunction(Object* object, void*);
-  static Object* ScriptGetEvalFromPosition(Object* object, void*);
+  static Object* ScriptGetEvalFromScript(Object* object, void*);
+  static Object* ScriptGetEvalFromScriptPosition(Object* object, void*);
+  static Object* ScriptGetEvalFromFunctionName(Object* object, void*);
   static Object* ObjectGetPrototype(Object* receiver, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);

=======================================
--- /branches/1.3/src/bootstrapper.cc   Wed Nov 25 09:06:33 2009
+++ /branches/1.3/src/bootstrapper.cc   Wed Jan  6 23:49:31 2010
@@ -1075,21 +1075,29 @@
             Factory::LookupAsciiSymbol("context_data"),
             proxy_context_data,
             common_attributes);
-    Handle<Proxy> proxy_eval_from_function =
-        Factory::NewProxy(&Accessors::ScriptEvalFromFunction);
+    Handle<Proxy> proxy_eval_from_script =
+        Factory::NewProxy(&Accessors::ScriptEvalFromScript);
     script_descriptors =
         Factory::CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("eval_from_function"),
-            proxy_eval_from_function,
+            Factory::LookupAsciiSymbol("eval_from_script"),
+            proxy_eval_from_script,
             common_attributes);
-    Handle<Proxy> proxy_eval_from_position =
-        Factory::NewProxy(&Accessors::ScriptEvalFromPosition);
+    Handle<Proxy> proxy_eval_from_script_position =
+        Factory::NewProxy(&Accessors::ScriptEvalFromScriptPosition);
     script_descriptors =
         Factory::CopyAppendProxyDescriptor(
             script_descriptors,
-            Factory::LookupAsciiSymbol("eval_from_position"),
-            proxy_eval_from_position,
+            Factory::LookupAsciiSymbol("eval_from_script_position"),
+            proxy_eval_from_script_position,
+            common_attributes);
+    Handle<Proxy> proxy_eval_from_function_name =
+        Factory::NewProxy(&Accessors::ScriptEvalFromFunctionName);
+    script_descriptors =
+        Factory::CopyAppendProxyDescriptor(
+            script_descriptors,
+            Factory::LookupAsciiSymbol("eval_from_function_name"),
+            proxy_eval_from_function_name,
             common_attributes);

     Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
=======================================
--- /branches/1.3/src/compiler.cc       Wed Nov 11 01:55:05 2009
+++ /branches/1.3/src/compiler.cc       Wed Jan  6 23:49:31 2010
@@ -165,7 +165,8 @@
     // called.
     if (is_eval) {
       JavaScriptFrameIterator it;
-      script->set_eval_from_function(it.frame()->function());
+      script->set_eval_from_shared(
+          JSFunction::cast(it.frame()->function())->shared());
int offset = it.frame()->pc() - it.frame()->code()->instruction_start();
       script->set_eval_from_instructions_offset(Smi::FromInt(offset));
     }
=======================================
--- /branches/1.3/src/factory.cc        Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/factory.cc        Wed Jan  6 23:49:31 2010
@@ -189,7 +189,7 @@
script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
   script->set_wrapper(*wrapper);
   script->set_line_ends(Heap::undefined_value());
-  script->set_eval_from_function(Heap::undefined_value());
+  script->set_eval_from_shared(Heap::undefined_value());
   script->set_eval_from_instructions_offset(Smi::FromInt(0));

   return script;
=======================================
--- /branches/1.3/src/globals.h Thu Oct 29 07:46:49 2009
+++ /branches/1.3/src/globals.h Wed Jan  6 23:49:31 2010
@@ -141,6 +141,14 @@
 const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
 const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;

+// Desired alignment for maps.
+#if V8_HOST_ARCH_64_BIT
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits;
+#else
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits + 3;
+#endif
+const intptr_t kMapAlignment = (1 << kMapAlignmentBits);
+const intptr_t kMapAlignmentMask = kMapAlignment - 1;

 // Tag information for Failure.
 const int kFailureTag = 3;
@@ -170,6 +178,11 @@
 #endif


+// Number of bits to represent the page size for paged spaces. The value of 13
+// gives 8K bytes per page.
+const int kPageSizeBits = 13;
+
+
 // Constants relevant to double precision floating point numbers.

 // Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
@@ -445,6 +458,10 @@
 #define POINTER_SIZE_ALIGN(value)                               \
   (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)

+// MAP_SIZE_ALIGN returns the value aligned as a map pointer.
+#define MAP_SIZE_ALIGN(value)                               \
+  (((value) + kMapAlignmentMask) & ~kMapAlignmentMask)
+
 // The expression OFFSET_OF(type, field) computes the byte-offset
 // of the specified field relative to the containing type. This
 // corresponds to 'offsetof' (in stddef.h), except that it doesn't
=======================================
--- /branches/1.3/src/heap-inl.h        Tue Aug 25 00:05:41 2009
+++ /branches/1.3/src/heap-inl.h        Wed Jan  6 23:49:31 2010
@@ -116,6 +116,12 @@
 #endif
   Object* result = map_space_->AllocateRaw(Map::kSize);
   if (result->IsFailure()) old_gen_exhausted_ = true;
+#ifdef DEBUG
+  if (!result->IsFailure()) {
+    // Maps have their own alignment.
+    CHECK((OffsetFrom(result) & kMapAlignmentMask) == kHeapObjectTag);
+  }
+#endif
   return result;
 }

=======================================
--- /branches/1.3/src/heap.cc   Tue Dec 15 14:00:44 2009
+++ /branches/1.3/src/heap.cc   Wed Jan  6 23:49:31 2010
@@ -1097,6 +1097,13 @@
   map->set_unused_property_fields(0);
   map->set_bit_field(0);
   map->set_bit_field2(0);
+
+  // If the map object is aligned fill the padding area with Smi 0 objects.
+  if (Map::kPadStart < Map::kSize) {
+    memset(reinterpret_cast<byte*>(map) + Map::kPadStart - kHeapObjectTag,
+           0,
+           Map::kSize - Map::kPadStart);
+  }
   return map;
 }

=======================================
--- /branches/1.3/src/heap.h    Mon Dec  7 02:32:14 2009
+++ /branches/1.3/src/heap.h    Wed Jan  6 23:49:31 2010
@@ -933,7 +933,10 @@
   static int linear_allocation_scope_depth_;
   static bool context_disposed_pending_;

-  static const int kMaxMapSpaceSize = 8*MB;
+  // The number of MapSpace pages is limited by the way we pack
+  // Map pointers during GC.
+  static const int kMaxMapSpaceSize =
+      (1 << (MapWord::kMapPageIndexBits)) * Page::kPageSize;

 #if defined(V8_TARGET_ARCH_X64)
   static const int kMaxObjectSizeInNewSpace = 512*KB;
=======================================
--- /branches/1.3/src/mark-compact.cc   Fri Oct 16 04:48:38 2009
+++ /branches/1.3/src/mark-compact.cc   Wed Jan  6 23:49:31 2010
@@ -888,11 +888,8 @@
 // space are encoded in their map pointer word (along with an encoding of
 // their map pointers).
 //
-//  31             21 20              10 9               0
-// +-----------------+------------------+-----------------+
-// |forwarding offset|page offset of map|page index of map|
-// +-----------------+------------------+-----------------+
-//  11 bits           11 bits            10 bits
+// The excact encoding is described in the comments for class MapWord in
+// objects.h.
 //
 // An address range [start, end) can have both live and non-live objects.
 // Maximal non-live regions are marked so they can be skipped on subsequent
=======================================
--- /branches/1.3/src/messages.js       Mon Nov 30 03:23:58 2009
+++ /branches/1.3/src/messages.js       Wed Jan  6 23:49:31 2010
@@ -629,10 +629,7 @@

 CallSite.prototype.getEvalOrigin = function () {
   var script = %FunctionGetScript(this.fun);
-  if (!script || script.compilation_type != 1)
-    return null;
-  return new CallSite(null, script.eval_from_function,
-      script.eval_from_position);
+  return FormatEvalOrigin(script);
 };

 CallSite.prototype.getFunction = function () {
@@ -700,7 +697,7 @@
   if (script) {
     location = script.locationFromPosition(this.pos, true);
   }
-  return location ? location.column : null;
+  return location ? location.column + 1: null;
 };

 CallSite.prototype.isNative = function () {
@@ -719,12 +716,44 @@
   return this.fun === constructor;
 };

+function FormatEvalOrigin(script) {
+  var eval_origin = "";
+  if (script.eval_from_function_name) {
+    eval_origin += script.eval_from_function_name;
+  } else {
+    eval_origin +=  "<anonymous>";
+  }
+
+  var eval_from_script = script.eval_from_script;
+  if (eval_from_script) {
+    if (eval_from_script.compilation_type == 1) {
+      // eval script originated from another eval.
+ eval_origin += " (eval at " + FormatEvalOrigin(eval_from_script) + ")";
+    } else {
+      // eval script originated from "real" scource.
+      if (eval_from_script.name) {
+        eval_origin += " (" + eval_from_script.name;
+ var location = eval_from_script.locationFromPosition(script.eval_from_script_position, true);
+        if (location) {
+          eval_origin += ":" + (location.line + 1);
+          eval_origin += ":" + (location.column + 1);
+        }
+        eval_origin += ")"
+      } else {
+        eval_origin += " (unknown source)";
+      }
+    }
+  }
+
+  return eval_origin;
+};
+
 function FormatSourcePosition(frame) {
   var fileLocation = "";
   if (frame.isNative()) {
     fileLocation = "native";
   } else if (frame.isEval()) {
- fileLocation = "eval at " + FormatSourcePosition(frame.getEvalOrigin());
+    fileLocation = "eval at " + frame.getEvalOrigin();
   } else {
     var fileName = frame.getFileName();
     if (fileName) {
=======================================
--- /branches/1.3/src/mirror-delay.js   Fri Oct 16 04:48:38 2009
+++ /branches/1.3/src/mirror-delay.js   Wed Jan  6 23:49:31 2010
@@ -1766,16 +1766,21 @@
 };


-ScriptMirror.prototype.evalFromFunction = function() {
-  return MakeMirror(this.script_.eval_from_function);
+ScriptMirror.prototype.evalFromScript = function() {
+  return MakeMirror(this.script_.eval_from_script);
 };


+ScriptMirror.prototype.evalFromFunctionName = function() {
+  return MakeMirror(this.script_.eval_from_function_name);
+};
+
+
 ScriptMirror.prototype.evalFromLocation = function() {
-  var eval_from_function = this.evalFromFunction();
-  if (!eval_from_function.isUndefined()) {
-    var position = this.script_.eval_from_position;
- return eval_from_function.script().locationFromPosition(position, true);
+  var eval_from_script = this.evalFromScript();
+  if (!eval_from_script.isUndefined()) {
+    var position = this.script_.eval_from_script_position;
+    return eval_from_script.locationFromPosition(position, true);
   }
 };

@@ -2053,12 +2058,15 @@
// For compilation type eval emit information on the script from which
       // eval was called if a script is present.
       if (mirror.compilationType() == 1 &&
-          mirror.evalFromFunction().script()) {
+          mirror.evalFromScript()) {
         content.evalFromScript =
-            this.serializeReference(mirror.evalFromFunction().script());
+            this.serializeReference(mirror.evalFromScript());
         var evalFromLocation = mirror.evalFromLocation()
         content.evalFromLocation = { line: evalFromLocation.line,
                                      column: evalFromLocation.column}
+        if (mirror.evalFromFunctionName()) {
+          content.evalFromFunctionName = mirror.evalFromFunctionName();
+        }
       }
       if (mirror.context()) {
         content.context = this.serializeReference(mirror.context());
=======================================
--- /branches/1.3/src/objects-debug.cc  Mon Nov 30 03:23:58 2009
+++ /branches/1.3/src/objects-debug.cc  Wed Jan  6 23:49:31 2010
@@ -1180,8 +1180,8 @@
   compilation_type()->ShortPrint();
   PrintF("\n - line ends: ");
   line_ends()->ShortPrint();
-  PrintF("\n - eval from function: ");
-  eval_from_function()->ShortPrint();
+  PrintF("\n - eval from shared: ");
+  eval_from_shared()->ShortPrint();
   PrintF("\n - eval from instructions offset: ");
   eval_from_instructions_offset()->ShortPrint();
   PrintF("\n");
=======================================
--- /branches/1.3/src/objects-inl.h     Tue Dec 15 14:00:44 2009
+++ /branches/1.3/src/objects-inl.h     Wed Jan  6 23:49:31 2010
@@ -992,14 +992,14 @@
   // exceed the object area size of a page.
   ASSERT(0 <= offset && offset < Page::kObjectAreaSize);

-  int compact_offset = offset >> kObjectAlignmentBits;
+  uintptr_t compact_offset = offset >> kObjectAlignmentBits;
   ASSERT(compact_offset < (1 << kForwardingOffsetBits));

   Page* map_page = Page::FromAddress(map_address);
   ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);

-  int map_page_offset =
-      map_page->Offset(map_address) >> kObjectAlignmentBits;
+  uintptr_t map_page_offset =
+      map_page->Offset(map_address) >> kMapAlignmentBits;

   uintptr_t encoding =
       (compact_offset << kForwardingOffsetShift) |
@@ -1015,8 +1015,8 @@
   ASSERT_MAP_PAGE_INDEX(map_page_index);

   int map_page_offset = static_cast<int>(
-      ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
-      << kObjectAlignmentBits);
+      ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
+      kMapAlignmentBits);

   return (map_space->PageAddress(map_page_index) + map_page_offset);
 }
@@ -2487,7 +2487,7 @@
 ACCESSORS(Script, type, Smi, kTypeOffset)
 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
-ACCESSORS(Script, eval_from_function, Object, kEvalFromFunctionOffset)
+ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
 ACCESSORS(Script, eval_from_instructions_offset, Smi,
           kEvalFrominstructionsOffsetOffset)

=======================================
--- /branches/1.3/src/objects.h Tue Dec 15 14:00:44 2009
+++ /branches/1.3/src/objects.h Wed Jan  6 23:49:31 2010
@@ -1152,15 +1152,25 @@
   static const int kOverflowBit = 1;  // overflow bit
   static const int kOverflowMask = (1 << kOverflowBit);  // overflow mask

-  // Forwarding pointers and map pointer encoding
-  //  31             21 20              10 9               0
+ // Forwarding pointers and map pointer encoding. On 32 bit all the bits are
+  // used.
   // +-----------------+------------------+-----------------+
   // |forwarding offset|page offset of map|page index of map|
   // +-----------------+------------------+-----------------+
-  //  11 bits           11 bits            10 bits
-  static const int kMapPageIndexBits = 10;
-  static const int kMapPageOffsetBits = 11;
-  static const int kForwardingOffsetBits = 11;
+  //          ^                 ^                  ^
+  //          |                 |                  |
+  //          |                 |          kMapPageIndexBits
+  //          |         kMapPageOffsetBits
+  // kForwardingOffsetBits
+  static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits;
+ static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits;
+#ifdef V8_HOST_ARCH_64_BIT
+  static const int kMapPageIndexBits = 16;
+#else
+  // Use all the 32-bits to encode on a 32-bit platform.
+  static const int kMapPageIndexBits =
+      32 - (kMapPageOffsetBits + kForwardingOffsetBits);
+#endif

   static const int kMapPageIndexShift = 0;
   static const int kMapPageOffsetShift =
@@ -1168,16 +1178,12 @@
   static const int kForwardingOffsetShift =
       kMapPageOffsetShift + kMapPageOffsetBits;

-  // 0x000003FF
-  static const uint32_t kMapPageIndexMask =
+  // Bit masks covering the different parts the encoding.
+  static const uintptr_t kMapPageIndexMask =
       (1 << kMapPageOffsetShift) - 1;
-
-  // 0x001FFC00
-  static const uint32_t kMapPageOffsetMask =
+  static const uintptr_t kMapPageOffsetMask =
       ((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
-
-  // 0xFFE00000
-  static const uint32_t kForwardingOffsetMask =
+  static const uintptr_t kForwardingOffsetMask =
       ~(kMapPageIndexMask | kMapPageOffsetMask);

  private:
@@ -3096,7 +3102,6 @@
   // [stub cache]: contains stubs compiled for this map.
   DECL_ACCESSORS(code_cache, FixedArray)

-  // Returns a copy of the map.
   Object* CopyDropDescriptors();

   // Returns a copy of the map, with all transitions dropped from the
@@ -3164,7 +3169,8 @@
   static const int kInstanceDescriptorsOffset =
       kConstructorOffset + kPointerSize;
static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
-  static const int kSize = kCodeCacheOffset + kPointerSize;
+  static const int kPadStart = kCodeCacheOffset + kPointerSize;
+  static const int kSize = MAP_SIZE_ALIGN(kPadStart);

   // Byte offsets within kInstanceSizesOffset.
   static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
@@ -3263,9 +3269,9 @@
   // [line_ends]: FixedArray of line ends positions.
   DECL_ACCESSORS(line_ends, Object)

-  // [eval_from_function]: for eval scripts the funcion from which eval was
-  // called.
-  DECL_ACCESSORS(eval_from_function, Object)
+  // [eval_from_shared]: for eval scripts the shared funcion info for the
+  // function from which eval was called.
+  DECL_ACCESSORS(eval_from_shared, Object)

// [eval_from_instructions_offset]: the instruction offset in the code for the
   // function from which eval was called where eval was called.
@@ -3293,9 +3299,9 @@
   static const int kCompilationTypeOffset = kTypeOffset + kPointerSize;
   static const int kLineEndsOffset = kCompilationTypeOffset + kPointerSize;
   static const int kIdOffset = kLineEndsOffset + kPointerSize;
-  static const int kEvalFromFunctionOffset = kIdOffset + kPointerSize;
+  static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
   static const int kEvalFrominstructionsOffsetOffset =
-      kEvalFromFunctionOffset + kPointerSize;
+      kEvalFromSharedOffset + kPointerSize;
static const int kSize = kEvalFrominstructionsOffsetOffset + kPointerSize;

  private:
=======================================
--- /branches/1.3/src/serialize.cc      Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/serialize.cc      Wed Jan  6 23:49:31 2010
@@ -1792,15 +1792,15 @@
       default: UNREACHABLE(); space = NULL; break;
     }
     ASSERT(size <= Page::kPageSize - Page::kObjectStartOffset);
-    int current_page = old_fullness >> Page::kPageSizeBits;
+    int current_page = old_fullness >> kPageSizeBits;
     int new_fullness = old_fullness + size;
-    int new_page = new_fullness >> Page::kPageSizeBits;
+    int new_page = new_fullness >> kPageSizeBits;
     // What is our new position within the current page.
     int intra_page_offset = new_fullness - current_page * Page::kPageSize;
     if (intra_page_offset > Page::kPageSize - Page::kObjectStartOffset) {
// This object will not fit in a page and we have to move to the next.
       new_page = current_page + 1;
-      old_fullness = new_page << Page::kPageSizeBits;
+      old_fullness = new_page << kPageSizeBits;
       new_fullness = old_fullness + size;
       record_page = true;
     }
@@ -1862,7 +1862,7 @@
   }
   ASSERT(SpaceIsPaged(space));
   int virtual_address = fullness_[space] - offset;
-  int page_of_pointee = (virtual_address) >> Page::kPageSizeBits;
+  int page_of_pointee = (virtual_address) >> kPageSizeBits;
   Address object_address = pages_[space][page_of_pointee] +
                            (virtual_address & Page::kPageAlignmentMask);
   return HeapObject::FromAddress(object_address);
=======================================
--- /branches/1.3/src/spaces.cc Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/spaces.cc Wed Jan  6 23:49:31 2010
@@ -398,7 +398,7 @@
   // start+size.  Page::kPageSize is a power of two so we can divide by
   // shifting.
   return (RoundDown(start + size, Page::kPageSize)
-          - RoundUp(start, Page::kPageSize)) >> Page::kPageSizeBits;
+          - RoundUp(start, Page::kPageSize)) >> kPageSizeBits;
 }


@@ -412,7 +412,7 @@
   if (size_ + static_cast<int>(chunk_size) > capacity_) {
     // Request as many pages as we can.
     chunk_size = capacity_ - size_;
-    requested_pages = chunk_size >> Page::kPageSizeBits;
+    requested_pages = chunk_size >> kPageSizeBits;

     if (requested_pages <= 0) return Page::FromAddress(NULL);
   }
=======================================
--- /branches/1.3/src/spaces.h  Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/spaces.h  Wed Jan  6 23:49:31 2010
@@ -65,20 +65,23 @@

 // Some assertion macros used in the debugging mode.

-#define ASSERT_PAGE_ALIGNED(address)                  \
+#define ASSERT_PAGE_ALIGNED(address) \
   ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0)

-#define ASSERT_OBJECT_ALIGNED(address)                \
+#define ASSERT_OBJECT_ALIGNED(address) \
   ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0)

-#define ASSERT_OBJECT_SIZE(size)                      \
+#define ASSERT_MAP_ALIGNED(address) \
+  ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0)
+
+#define ASSERT_OBJECT_SIZE(size) \
   ASSERT((0 < size) && (size <= Page::kMaxHeapObjectSize))

-#define ASSERT_PAGE_OFFSET(offset)                    \
-  ASSERT((Page::kObjectStartOffset <= offset)         \
+#define ASSERT_PAGE_OFFSET(offset) \ + ASSERT((Page::kObjectStartOffset <= offset) \
       && (offset <= Page::kPageSize))

-#define ASSERT_MAP_PAGE_INDEX(index)                            \
+#define ASSERT_MAP_PAGE_INDEX(index) \
   ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex))


@@ -106,11 +109,8 @@
// For this reason we add an offset to get room for the Page data at the start.
 //
// The mark-compact collector transforms a map pointer into a page index and a -// page offset. The map space can have up to 1024 pages, and 8M bytes (1024 *
-// 8K) in total.  Because a map pointer is aligned to the pointer size (4
-// bytes), 11 bits are enough to encode the page offset. 21 bits (10 for the
-// page index + 11 for the offset in the page) are required to encode a map
-// pointer.
+// page offset. The excact encoding is described in the comments for
+// class MapWord in objects.h.
 //
 // The only way to get a page pointer is by calling factory methods:
 //   Page* p = Page::FromAddress(addr); or
@@ -212,9 +212,6 @@
   static void set_rset_state(RSetState state) { rset_state_ = state; }
 #endif

-  // 8K bytes per page.
-  static const int kPageSizeBits = 13;
-
   // Page size in bytes.  This must be a multiple of the OS page size.
   static const int kPageSize = 1 << kPageSizeBits;

@@ -514,7 +511,7 @@
 #endif

   // Due to encoding limitation, we can only have 8K chunks.
-  static const int kMaxNofChunks = 1 << Page::kPageSizeBits;
+  static const int kMaxNofChunks = 1 << kPageSizeBits;
   // If a chunk has at least 16 pages, the maximum heap size is about
   // 8K * 8K * 16 = 1G bytes.
 #ifdef V8_TARGET_ARCH_X64
=======================================
--- /branches/1.3/src/version.cc        Tue Dec 15 23:33:08 2009
+++ /branches/1.3/src/version.cc        Wed Jan  6 23:49:31 2010
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     1
 #define MINOR_VERSION     3
 #define BUILD_NUMBER      18
-#define PATCH_LEVEL       17
+#define PATCH_LEVEL       18
 #define CANDIDATE_VERSION false

 // Define SONAME to have the SCons build the put a specific SONAME into the
=======================================
--- /branches/1.3/test/cctest/test-api.cc       Mon Nov 30 03:23:58 2009
+++ /branches/1.3/test/cctest/test-api.cc       Wed Jan  6 23:49:31 2010
@@ -8719,26 +8719,27 @@
   v8::internal::HeapIterator it;
   while (it.has_next()) {
     v8::internal::HeapObject* object = it.next();
-    if (object->IsJSGlobalObject()) {
-      count++;
-    }
-  }
-#ifdef DEBUG
-  if (count > 0) v8::internal::Heap::TracePathToGlobal();
-#endif
+    if (object->IsJSGlobalObject()) count++;
+  }
   return count;
 }


-TEST(Bug528) {
+TEST(Regress528) {
   v8::V8::Initialize();

   v8::HandleScope scope;
   v8::Persistent<Context> context;
+  v8::Persistent<Context> other_context;
   int gc_count;

+  // Create a context used to keep the code from aging in the compilation
+  // cache.
+  other_context = Context::New();
+
   // Context-dependent context data creates reference from the compilation
   // cache to the global object.
+  const char* source_simple = "1";
   context = Context::New();
   {
     v8::HandleScope scope;
@@ -8746,44 +8747,52 @@
     context->Enter();
     Local<v8::String> obj = v8::String::New("");
     context->SetData(obj);
-    CompileRun("1");
+    CompileRun(source_simple);
     context->Exit();
   }
   context.Dispose();
   for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_simple);
+    other_context->Exit();
     v8::internal::Heap::CollectAllGarbage(false);
-    if (GetGlobalObjectsCount() == 0) break;
-  }
-  CHECK_EQ(0, GetGlobalObjectsCount());
-  CHECK_EQ(2, gc_count);
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());

   // Eval in a function creates reference from the compilation cache to the
   // global object.
+  const char* source_eval = "function f(){eval('1')}; f()";
   context = Context::New();
   {
     v8::HandleScope scope;

     context->Enter();
-    CompileRun("function f(){eval('1')}; f()");
+    CompileRun(source_eval);
     context->Exit();
   }
   context.Dispose();
   for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_eval);
+    other_context->Exit();
     v8::internal::Heap::CollectAllGarbage(false);
-    if (GetGlobalObjectsCount() == 0) break;
-  }
-  CHECK_EQ(0, GetGlobalObjectsCount());
-  CHECK_EQ(2, gc_count);
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());

   // Looking up the line number for an exception creates reference from the
   // compilation cache to the global object.
+  const char* source_exception = "function f(){throw 1;} f()";
   context = Context::New();
   {
     v8::HandleScope scope;

     context->Enter();
     v8::TryCatch try_catch;
-    CompileRun("function f(){throw 1;}; f()");
+    CompileRun(source_exception);
     CHECK(try_catch.HasCaught());
     v8::Handle<v8::Message> message = try_catch.Message();
     CHECK(!message.IsEmpty());
@@ -8792,9 +8801,14 @@
   }
   context.Dispose();
   for (gc_count = 1; gc_count < 10; gc_count++) {
+    other_context->Enter();
+    CompileRun(source_exception);
+    other_context->Exit();
     v8::internal::Heap::CollectAllGarbage(false);
-    if (GetGlobalObjectsCount() == 0) break;
-  }
-  CHECK_EQ(0, GetGlobalObjectsCount());
-  CHECK_EQ(2, gc_count);
-}
+    if (GetGlobalObjectsCount() == 1) break;
+  }
+  CHECK_GE(2, gc_count);
+  CHECK_EQ(1, GetGlobalObjectsCount());
+
+  other_context.Dispose();
+}
=======================================
--- /branches/1.3/test/mjsunit/mjsunit.status   Wed Nov 11 01:11:58 2009
+++ /branches/1.3/test/mjsunit/mjsunit.status   Wed Jan  6 23:49:31 2010
@@ -42,6 +42,10 @@
 # Issue 499
 cyrillic: PASS, TIMEOUT if ($arch == arm)

+# Skip long running test in debug.
+regress/regress-524: PASS, SKIP if $mode == debug
+
+
 [ $arch == arm ]

 # Slow tests which times out in debug mode.
-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to