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