Revision: 3321
Author: [email protected]
Date: Tue Nov 17 13:43:00 2009
Log: Merge r3285, r3313, and r3318 to branches/1.3. This includes fixes to
avoid bogus FatalProcessOutOfMemory issues (3285), 13.4% compiled code size
reduction (3313), and a critical fix to avoid potentially orphaning global
handles (3318).
Review URL: http://codereview.chromium.org/399044
http://code.google.com/p/v8/source/detail?r=3321
Modified:
/branches/1.3/src/global-handles.cc
/branches/1.3/src/heap.cc
/branches/1.3/src/ia32/codegen-ia32.cc
/branches/1.3/src/ia32/codegen-ia32.h
/branches/1.3/src/ia32/register-allocator-ia32.cc
/branches/1.3/src/ia32/virtual-frame-ia32.cc
/branches/1.3/src/runtime.cc
/branches/1.3/src/version.cc
/branches/1.3/test/cctest/test-api.cc
=======================================
--- /branches/1.3/src/global-handles.cc Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/global-handles.cc Tue Nov 17 13:43:00 2009
@@ -165,6 +165,9 @@
// It's fine though to reuse nodes that were destroyed in weak
callback
// as those cannot be deallocated until we are back from the
callback.
set_first_free(NULL);
+ if (first_deallocated()) {
+ first_deallocated()->set_next(head());
+ }
// Leaving V8.
VMState state(EXTERNAL);
func(object, par);
@@ -270,6 +273,7 @@
// Next try deallocated list
result = first_deallocated();
set_first_deallocated(result->next_free());
+ ASSERT(result->next() == head());
set_head(result);
} else {
// Allocate a new node.
=======================================
--- /branches/1.3/src/heap.cc Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/heap.cc Tue Nov 17 13:43:00 2009
@@ -1730,6 +1730,7 @@
// Statically ensure that it is safe to allocate proxies in paged spaces.
STATIC_ASSERT(Proxy::kSize <= Page::kMaxHeapObjectSize);
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE :
NEW_SPACE;
+ if (always_allocate()) space = OLD_DATA_SPACE;
Object* result = Allocate(proxy_map(), space);
if (result->IsFailure()) return result;
@@ -1821,12 +1822,13 @@
: long_cons_string_map();
}
- Object* result = Allocate(map, NEW_SPACE);
+ Object* result = Allocate(map,
+ always_allocate() ? OLD_POINTER_SPACE :
NEW_SPACE);
if (result->IsFailure()) return result;
- ASSERT(InNewSpace(result));
ConsString* cons_string = ConsString::cast(result);
- cons_string->set_first(first, SKIP_WRITE_BARRIER);
- cons_string->set_second(second, SKIP_WRITE_BARRIER);
+ WriteBarrierMode mode = cons_string->GetWriteBarrierMode();
+ cons_string->set_first(first, mode);
+ cons_string->set_second(second, mode);
cons_string->set_length(length);
return result;
}
@@ -1920,7 +1922,8 @@
map = long_external_ascii_string_map();
}
- Object* result = Allocate(map, NEW_SPACE);
+ Object* result = Allocate(map,
+ always_allocate() ? OLD_DATA_SPACE :
NEW_SPACE);
if (result->IsFailure()) return result;
ExternalAsciiString* external_string = ExternalAsciiString::cast(result);
@@ -1936,7 +1939,8 @@
int length = resource->length();
Map* map = ExternalTwoByteString::StringMap(length);
- Object* result = Allocate(map, NEW_SPACE);
+ Object* result = Allocate(map,
+ always_allocate() ? OLD_DATA_SPACE :
NEW_SPACE);
if (result->IsFailure()) return result;
ExternalTwoByteString* external_string =
ExternalTwoByteString::cast(result);
@@ -2321,6 +2325,7 @@
AllocationSpace space =
(pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
if (map->instance_size() > MaxObjectSizeInPagedSpace()) space = LO_SPACE;
+ if (always_allocate()) space = OLD_POINTER_SPACE;
Object* obj = Allocate(map, space);
if (obj->IsFailure()) return obj;
=======================================
--- /branches/1.3/src/ia32/codegen-ia32.cc Thu Oct 29 07:46:49 2009
+++ /branches/1.3/src/ia32/codegen-ia32.cc Tue Nov 17 13:43:00 2009
@@ -3958,12 +3958,28 @@
}
-void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) {
+void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
+ ASSERT(value->IsSmi());
+ int bits = reinterpret_cast<int>(*value);
+ __ push(Immediate(bits & 0x0000FFFF));
+ __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000));
+}
+
+
+void CodeGenerator::StoreUnsafeSmiToLocal(int offset, Handle<Object>
value) {
+ ASSERT(value->IsSmi());
+ int bits = reinterpret_cast<int>(*value);
+ __ mov(Operand(ebp, offset), Immediate(bits & 0x0000FFFF));
+ __ or_(Operand(ebp, offset), Immediate(bits & 0xFFFF0000));
+}
+
+
+void CodeGenerator::MoveUnsafeSmi(Register target, Handle<Object> value) {
ASSERT(target.is_valid());
ASSERT(value->IsSmi());
int bits = reinterpret_cast<int>(*value);
__ Set(target, Immediate(bits & 0x0000FFFF));
- __ xor_(target, bits & 0xFFFF0000);
+ __ or_(target, bits & 0xFFFF0000);
}
=======================================
--- /branches/1.3/src/ia32/codegen-ia32.h Wed Oct 28 07:53:37 2009
+++ /branches/1.3/src/ia32/codegen-ia32.h Tue Nov 17 13:43:00 2009
@@ -484,9 +484,11 @@
// than 16 bits.
static const int kMaxSmiInlinedBits = 16;
bool IsUnsafeSmi(Handle<Object> value);
- // Load an integer constant x into a register target using
+ // Load an integer constant x into a register target or into the stack
using
// at most 16 bits of user-controlled data per assembly operation.
- void LoadUnsafeSmi(Register target, Handle<Object> value);
+ void MoveUnsafeSmi(Register target, Handle<Object> value);
+ void StoreUnsafeSmiToLocal(int offset, Handle<Object> value);
+ void PushUnsafeSmi(Handle<Object> value);
void CallWithArguments(ZoneList<Expression*>* arguments, int position);
=======================================
--- /branches/1.3/src/ia32/register-allocator-ia32.cc Wed Sep 9 12:27:10
2009
+++ /branches/1.3/src/ia32/register-allocator-ia32.cc Tue Nov 17 13:43:00
2009
@@ -42,7 +42,7 @@
Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
ASSERT(fresh.is_valid());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
- CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle());
+ CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(), handle());
} else {
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle()));
@@ -64,7 +64,7 @@
} else {
ASSERT(is_constant());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
- CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(),
handle());
+ CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(),
handle());
} else {
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle()));
=======================================
--- /branches/1.3/src/ia32/virtual-frame-ia32.cc Wed Nov 11 01:17:04 2009
+++ /branches/1.3/src/ia32/virtual-frame-ia32.cc Tue Nov 17 13:43:00 2009
@@ -75,10 +75,7 @@
case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(element.handle())) {
- Result temp = cgen()->allocator()->Allocate();
- ASSERT(temp.is_valid());
- cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
- __ mov(Operand(ebp, fp_relative(index)), temp.reg());
+ cgen()->StoreUnsafeSmiToLocal(fp_relative(index),
element.handle());
} else {
__ Set(Operand(ebp, fp_relative(index)),
Immediate(element.handle()));
@@ -127,10 +124,7 @@
case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(element.handle())) {
- Result temp = cgen()->allocator()->Allocate();
- ASSERT(temp.is_valid());
- cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
- __ push(temp.reg());
+ cgen()->PushUnsafeSmi(element.handle());
} else {
__ push(Immediate(element.handle()));
}
@@ -161,15 +155,16 @@
// on the stack.
int start = Min(begin, stack_pointer_ + 1);
- // If positive we have to adjust the stack pointer.
- int delta = end - stack_pointer_;
- if (delta > 0) {
- stack_pointer_ = end;
- __ sub(Operand(esp), Immediate(delta * kPointerSize));
- }
-
+ // Emit normal push instructions for elements above stack pointer
+ // and use mov instructions if we are below stack pointer.
for (int i = start; i <= end; i++) {
- if (!elements_[i].is_synced()) SyncElementBelowStackPointer(i);
+ if (!elements_[i].is_synced()) {
+ if (i <= stack_pointer_) {
+ SyncElementBelowStackPointer(i);
+ } else {
+ SyncElementByPushing(i);
+ }
+ }
}
}
@@ -198,7 +193,7 @@
// Emit a move.
if (element.is_constant()) {
if (cgen()->IsUnsafeSmi(element.handle())) {
- cgen()->LoadUnsafeSmi(fresh.reg(), element.handle());
+ cgen()->MoveUnsafeSmi(fresh.reg(), element.handle());
} else {
__ Set(fresh.reg(), Immediate(element.handle()));
}
@@ -299,7 +294,7 @@
if (!source.is_synced()) {
if (cgen()->IsUnsafeSmi(source.handle())) {
esi_caches = i;
- cgen()->LoadUnsafeSmi(esi, source.handle());
+ cgen()->MoveUnsafeSmi(esi, source.handle());
__ mov(Operand(ebp, fp_relative(i)), esi);
} else {
__ Set(Operand(ebp, fp_relative(i)),
Immediate(source.handle()));
@@ -407,7 +402,7 @@
case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(source.handle())) {
- cgen()->LoadUnsafeSmi(target_reg, source.handle());
+ cgen()->MoveUnsafeSmi(target_reg, source.handle());
} else {
__ Set(target_reg, Immediate(source.handle()));
}
=======================================
--- /branches/1.3/src/runtime.cc Wed Nov 11 02:11:16 2009
+++ /branches/1.3/src/runtime.cc Tue Nov 17 13:43:00 2009
@@ -4336,8 +4336,6 @@
Object* result = Heap::AllocateArgumentsObject(callee, length);
if (result->IsFailure()) return result;
- ASSERT(Heap::InNewSpace(result));
-
// Allocate the elements if needed.
if (length > 0) {
// Allocate the fixed array.
@@ -4350,8 +4348,7 @@
for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode);
}
- JSObject::cast(result)->set_elements(FixedArray::cast(obj),
- SKIP_WRITE_BARRIER);
+ JSObject::cast(result)->set_elements(FixedArray::cast(obj));
}
return result;
}
=======================================
--- /branches/1.3/src/version.cc Tue Nov 17 01:53:59 2009
+++ /branches/1.3/src/version.cc Tue Nov 17 13:43:00 2009
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 1
#define MINOR_VERSION 3
#define BUILD_NUMBER 18
-#define PATCH_LEVEL 9
+#define PATCH_LEVEL 10
#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 Fri Nov 13 00:04:17 2009
+++ /branches/1.3/test/cctest/test-api.cc Tue Nov 17 13:43:00 2009
@@ -6450,6 +6450,31 @@
to_be_disposed = handle2;
i::Heap::CollectAllGarbage(false);
}
+
+void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
+ handle.Dispose();
+}
+
+void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
+ v8::HandleScope scope;
+ v8::Persistent<v8::Object>::New(v8::Object::New());
+}
+
+
+THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
+ LocalContext context;
+
+ v8::Persistent<v8::Object> handle1, handle2, handle3;
+ {
+ v8::HandleScope scope;
+ handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
+ }
+ handle2.MakeWeak(NULL, DisposingCallback);
+ handle3.MakeWeak(NULL, HandleCreatingCallback);
+ i::Heap::CollectAllGarbage(false);
+}
THREADED_TEST(CheckForCrossContextObjectLiterals) {
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---