Merge v8 from https://chromium.googlesource.com/external/v8.git at 5d6da6c9b6d98c3e7948ff7999812bb62513b906
This commit was generated by merge_from_chromium.py.
Change-Id: Ia7c9bc83d21f56c1e5e9a74fd9dbd58022fece2c
diff --git a/ChangeLog b/ChangeLog
index f41f017..b041111 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-04-29: Version 3.26.27
+
+ Error stack getter should not overwrite itself with a data property
+ (issue 3294).
+
+ Performance and stability improvements on all platforms.
+
+
2014-04-28: Version 3.26.26
Expose promise value through promise mirror (issue 3093).
diff --git a/src/accessors.cc b/src/accessors.cc
index eb99faa..f0f7791 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -1096,26 +1096,47 @@
}
-Object* Accessors::FunctionGetArguments(Isolate* isolate,
- Object* object,
- void*) {
+void Accessors::FunctionArgumentsGetter(
+ v8::Local<v8::String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<JSFunction> function;
+ Handle<Object> object = Utils::OpenHandle(*info.This());
+ MaybeHandle<JSFunction> maybe_function;
+
{
DisallowHeapAllocation no_allocation;
- JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
- if (holder == NULL) return isolate->heap()->undefined_value();
- function = Handle<JSFunction>(holder, isolate);
+ JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
+ if (function != NULL) maybe_function = Handle<JSFunction>(function);
}
- return *GetFunctionArguments(isolate, function);
+
+ Handle<JSFunction> function;
+ Handle<Object> result;
+ if (maybe_function.ToHandle(&function)) {
+ result = GetFunctionArguments(isolate, function);
+ } else {
+ result = isolate->factory()->undefined_value();
+ }
+ info.GetReturnValue().Set(Utils::ToLocal(result));
}
-const AccessorDescriptor Accessors::FunctionArguments = {
- FunctionGetArguments,
- ReadOnlySetAccessor,
- 0
-};
+void Accessors::FunctionArgumentsSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> val,
+ const v8::PropertyCallbackInfo<void>& info) {
+ // Do nothing.
+}
+
+
+Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
+ Isolate* isolate, PropertyAttributes attributes) {
+ return MakeAccessor(isolate,
+ isolate->factory()->arguments_string(),
+ &FunctionArgumentsGetter,
+ &FunctionArgumentsSetter,
+ attributes);
+}
//
diff --git a/src/accessors.h b/src/accessors.h
index db63fda..2dcb860 100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -37,11 +37,11 @@
// The list of accessor descriptors. This is a second-order macro
// taking a macro to be applied to all accessor descriptor names.
#define ACCESSOR_DESCRIPTOR_LIST(V) \
- V(FunctionArguments) \
V(FunctionCaller) \
V(ArrayLength)
#define ACCESSOR_INFO_LIST(V) \
+ V(FunctionArguments) \
V(FunctionName) \
V(FunctionLength) \
V(FunctionPrototype) \
@@ -114,21 +114,6 @@
int* object_offset);
private:
- // Accessor functions only used through the descriptor.
- static Object* FunctionSetPrototype(Isolate* isolate,
- JSObject* object,
- Object*,
- void*);
- static Object* FunctionGetPrototype(Isolate* isolate,
- Object* object,
- void*);
- static Object* FunctionGetLength(Isolate* isolate,
- Object* object,
- void*);
- static Object* FunctionGetName(Isolate* isolate, Object* object, void*);
- static Object* FunctionGetArguments(Isolate* isolate,
- Object* object,
- void*);
static Object* FunctionGetCaller(Isolate* isolate,
Object* object,
void*);
diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
index 0c6b2ad..59ef878 100644
--- a/src/arm/lithium-gap-resolver-arm.cc
+++ b/src/arm/lithium-gap-resolver-arm.cc
@@ -33,11 +33,22 @@
namespace v8 {
namespace internal {
-static const Register kSavedValueRegister = { 9 };
+// We use the root register to spill a value while breaking a cycle in parallel
+// moves. We don't need access to roots while resolving the move list and using
+// the root register has two advantages:
+// - It is not in crankshaft allocatable registers list, so it can't interfere
+// with any of the moves we are resolving.
+// - We don't need to push it on the stack, as we can reload it with its value
+// once we have resolved a cycle.
+#define kSavedValueRegister kRootRegister
+
LGapResolver::LGapResolver(LCodeGen* owner)
: cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false),
- saved_destination_(NULL) { }
+ saved_destination_(NULL), need_to_restore_root_(false) { }
+
+
+#define __ ACCESS_MASM(cgen_->masm())
void LGapResolver::Resolve(LParallelMove* parallel_move) {
@@ -67,6 +78,12 @@
}
}
+ if (need_to_restore_root_) {
+ ASSERT(kSavedValueRegister.is(kRootRegister));
+ __ InitializeRootRegister();
+ need_to_restore_root_ = false;
+ }
+
moves_.Rewind(0);
}
@@ -155,20 +172,21 @@
#endif
}
-#define __ ACCESS_MASM(cgen_->masm())
void LGapResolver::BreakCycle(int index) {
- // We save in a register the value that should end up in the source of
- // moves_[root_index]. After performing all moves in the tree rooted
- // in that move, we save the value to that source.
+ // We save in a register the source of that move and we remember its
+ // destination. Then we mark this move as resolved so the cycle is
+ // broken and we can perform the other moves.
ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
ASSERT(!in_cycle_);
in_cycle_ = true;
LOperand* source = moves_[index].source();
saved_destination_ = moves_[index].destination();
if (source->IsRegister()) {
+ need_to_restore_root_ = true;
__ mov(kSavedValueRegister, cgen_->ToRegister(source));
} else if (source->IsStackSlot()) {
+ need_to_restore_root_ = true;
__ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) {
__ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
@@ -186,7 +204,6 @@
ASSERT(in_cycle_);
ASSERT(saved_destination_ != NULL);
- // Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister.
if (saved_destination_->IsRegister()) {
__ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
} else if (saved_destination_->IsStackSlot()) {
@@ -226,20 +243,15 @@
} else {
ASSERT(destination->IsStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination);
- if (in_cycle_) {
- if (!destination_operand.OffsetIsUint12Encodable()) {
- // ip is overwritten while saving the value to the destination.
- // Therefore we can't use ip. It is OK if the read from the source
- // destroys ip, since that happens before the value is read.
- __ vldr(kScratchDoubleReg.low(), source_operand);
- __ vstr(kScratchDoubleReg.low(), destination_operand);
- } else {
- __ ldr(ip, source_operand);
- __ str(ip, destination_operand);
- }
+ if (!destination_operand.OffsetIsUint12Encodable()) {
+ // ip is overwritten while saving the value to the destination.
+ // Therefore we can't use ip. It is OK if the read from the source
+ // destroys ip, since that happens before the value is read.
+ __ vldr(kScratchDoubleReg.low(), source_operand);
+ __ vstr(kScratchDoubleReg.low(), destination_operand);
} else {
- __ ldr(kSavedValueRegister, source_operand);
- __ str(kSavedValueRegister, destination_operand);
+ __ ldr(ip, source_operand);
+ __ str(ip, destination_operand);
}
}
@@ -261,14 +273,14 @@
} else {
ASSERT(destination->IsStackSlot());
ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
+ need_to_restore_root_ = true;
Representation r = cgen_->IsSmi(constant_source)
? Representation::Smi() : Representation::Integer32();
if (cgen_->IsInteger32(constant_source)) {
__ mov(kSavedValueRegister,
Operand(cgen_->ToRepresentation(constant_source, r)));
} else {
- __ Move(kSavedValueRegister,
- cgen_->ToHandle(constant_source));
+ __ Move(kSavedValueRegister, cgen_->ToHandle(constant_source));
}
__ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
}
@@ -290,16 +302,11 @@
ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) {
- // kSavedDoubleValueRegister was used to break the cycle,
- // but kSavedValueRegister is free.
- MemOperand source_high_operand =
- cgen_->ToHighMemOperand(source);
- MemOperand destination_high_operand =
- cgen_->ToHighMemOperand(destination);
- __ ldr(kSavedValueRegister, source_operand);
- __ str(kSavedValueRegister, destination_operand);
- __ ldr(kSavedValueRegister, source_high_operand);
- __ str(kSavedValueRegister, destination_high_operand);
+ // kScratchDoubleReg was used to break the cycle.
+ __ vstm(db_w, sp, kScratchDoubleReg, kScratchDoubleReg);
+ __ vldr(kScratchDoubleReg, source_operand);
+ __ vstr(kScratchDoubleReg, destination_operand);
+ __ vldm(ia_w, sp, kScratchDoubleReg, kScratchDoubleReg);
} else {
__ vldr(kScratchDoubleReg, source_operand);
__ vstr(kScratchDoubleReg, destination_operand);
diff --git a/src/arm/lithium-gap-resolver-arm.h b/src/arm/lithium-gap-resolver-arm.h
index 044c286..066f880 100644
--- a/src/arm/lithium-gap-resolver-arm.h
+++ b/src/arm/lithium-gap-resolver-arm.h
@@ -76,6 +76,10 @@
int root_index_;
bool in_cycle_;
LOperand* saved_destination_;
+
+ // We use the root register as a scratch in a few places. When that happens,
+ // this flag is set to indicate that it needs to be restored.
+ bool need_to_restore_root_;
};
} } // namespace v8::internal
diff --git a/src/array.js b/src/array.js
index 104fe3f..ab8bb39 100644
--- a/src/array.js
+++ b/src/array.js
@@ -1147,28 +1147,16 @@
var result = new $Array();
var accumulator = new InternalArray();
var accumulator_length = 0;
- if (%DebugCallbackSupportsStepping(f)) {
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(f);
- if (%_CallFunction(receiver, element, i, array, f)) {
- accumulator[accumulator_length++] = element;
- }
+ var stepping = %_DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ if (%_CallFunction(receiver, element, i, array, f)) {
+ accumulator[accumulator_length++] = element;
}
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- if (%_CallFunction(receiver, element, i, array, f)) {
- accumulator[accumulator_length++] = element;
- }
- }
- }
- // End of duplicate.
}
%MoveArrayContents(accumulator, result);
return result;
@@ -1192,24 +1180,14 @@
receiver = ToObject(receiver);
}
- if (%DebugCallbackSupportsStepping(f)) {
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(f);
- %_CallFunction(receiver, element, i, array, f);
- }
+ var stepping = %_DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ %_CallFunction(receiver, element, i, array, f);
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- %_CallFunction(receiver, element, i, array, f);
- }
- }
- // End of duplicate.
}
}
@@ -1233,24 +1211,14 @@
receiver = ToObject(receiver);
}
- if (%DebugCallbackSupportsStepping(f)) {
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(f);
- if (%_CallFunction(receiver, element, i, array, f)) return true;
- }
+ var stepping = %_DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ if (%_CallFunction(receiver, element, i, array, f)) return true;
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- if (%_CallFunction(receiver, element, i, array, f)) return true;
- }
- }
- // End of duplicate.
}
return false;
}
@@ -1273,24 +1241,14 @@
receiver = ToObject(receiver);
}
- if (%DebugCallbackSupportsStepping(f)) {
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(f);
- if (!%_CallFunction(receiver, element, i, array, f)) return false;
- }
+ var stepping = %_DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ if (!%_CallFunction(receiver, element, i, array, f)) return false;
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- if (!%_CallFunction(receiver, element, i, array, f)) return false;
- }
- }
- // End of duplicate.
}
return true;
}
@@ -1314,24 +1272,14 @@
var result = new $Array();
var accumulator = new InternalArray(length);
- if (%DebugCallbackSupportsStepping(f)) {
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(f);
- accumulator[i] = %_CallFunction(receiver, element, i, array, f);
- }
+ var stepping = %_DebugCallbackSupportsStepping(f);
+ for (var i = 0; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ accumulator[i] = %_CallFunction(receiver, element, i, array, f);
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (var i = 0; i < length; i++) {
- if (i in array) {
- var element = array[i];
- accumulator[i] = %_CallFunction(receiver, element, i, array, f);
- }
- }
- // End of duplicate.
}
%MoveArrayContents(accumulator, result);
return result;
@@ -1471,27 +1419,14 @@
}
var receiver = %GetDefaultReceiver(callback);
-
- if (%DebugCallbackSupportsStepping(callback)) {
- for (; i < length; i++) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(callback);
- current =
- %_CallFunction(receiver, current, element, i, array, callback);
- }
+ var stepping = %_DebugCallbackSupportsStepping(callback);
+ for (; i < length; i++) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(callback);
+ current = %_CallFunction(receiver, current, element, i, array, callback);
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (; i < length; i++) {
- if (i in array) {
- var element = array[i];
- current =
- %_CallFunction(receiver, current, element, i, array, callback);
- }
- }
- // End of duplicate.
}
return current;
}
@@ -1521,27 +1456,14 @@
}
var receiver = %GetDefaultReceiver(callback);
-
- if (%DebugCallbackSupportsStepping(callback)) {
- for (; i >= 0; i--) {
- if (i in array) {
- var element = array[i];
- // Prepare break slots for debugger step in.
- %DebugPrepareStepInIfStepping(callback);
- current =
- %_CallFunction(receiver, current, element, i, array, callback);
- }
+ var stepping = %_DebugCallbackSupportsStepping(callback);
+ for (; i >= 0; i--) {
+ if (i in array) {
+ var element = array[i];
+ // Prepare break slots for debugger step in.
+ if (stepping) %DebugPrepareStepInIfStepping(callback);
+ current = %_CallFunction(receiver, current, element, i, array, callback);
}
- } else {
- // This is a duplicate of the previous loop sans debug stepping.
- for (; i >= 0; i--) {
- if (i in array) {
- var element = array[i];
- current =
- %_CallFunction(receiver, current, element, i, array, callback);
- }
- }
- // End of duplicate.
}
return current;
}
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index d577772..775db59 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -388,7 +388,6 @@
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
Map::EnsureDescriptorSlack(map, size);
- Handle<Foreign> args(factory()->NewForeign(&Accessors::FunctionArguments));
Handle<Foreign> caller(factory()->NewForeign(&Accessors::FunctionCaller));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
@@ -407,8 +406,11 @@
name, attribs);
map->AppendDescriptor(&d);
}
+ Handle<AccessorInfo> args =
+ Accessors::FunctionArgumentsInfo(isolate(), attribs);
{ // Add arguments.
- CallbacksDescriptor d(factory()->arguments_string(), args, attribs);
+ CallbacksDescriptor d(Handle<Name>(Name::cast(args->name())),
+ args, attribs);
map->AppendDescriptor(&d);
}
{ // Add caller.
diff --git a/src/frames.cc b/src/frames.cc
index 46dd5ef..e6fee95 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -990,13 +990,10 @@
it.Next(); // Skip height.
// The translation commands are ordered and the receiver is always
- // at the first position. Since we are always at a call when we need
- // to construct a stack trace, the receiver is always in a stack slot.
+ // at the first position.
+ // If we are at a call, the receiver is always in a stack slot.
+ // Otherwise we are not guaranteed to get the receiver value.
opcode = static_cast<Translation::Opcode>(it.Next());
- ASSERT(opcode == Translation::STACK_SLOT ||
- opcode == Translation::LITERAL ||
- opcode == Translation::CAPTURED_OBJECT ||
- opcode == Translation::DUPLICATED_OBJECT);
int index = it.Next();
// Get the correct receiver in the optimized frame.
@@ -1020,6 +1017,7 @@
: this->GetParameter(parameter_index);
}
} else {
+ // The receiver is not in a stack slot nor in a literal. We give up.
// TODO(3029): Materializing a captured object (or duplicated
// object) is hard, we return undefined for now. This breaks the
// produced stack trace, as constructor frames aren't marked as
diff --git a/src/heap.cc b/src/heap.cc
index ebf9f8f..f6785b9 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1517,9 +1517,6 @@
incremental_marking()->PrepareForScavenge();
- paged_space(OLD_DATA_SPACE)->EnsureSweeperProgress(new_space_.Size());
- paged_space(OLD_POINTER_SPACE)->EnsureSweeperProgress(new_space_.Size());
-
// Flip the semispaces. After flipping, to space is empty, from space has
// live objects.
new_space_.Flip();
diff --git a/src/heap.h b/src/heap.h
index 48761e8..0bfa9bb 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1549,12 +1549,6 @@
return &incremental_marking_;
}
- bool EnsureSweepersProgressed(int step_size) {
- bool sweeping_complete = old_data_space()->EnsureSweeperProgress(step_size);
- sweeping_complete &= old_pointer_space()->EnsureSweeperProgress(step_size);
- return sweeping_complete;
- }
-
ExternalStringTable* external_string_table() {
return &external_string_table_;
}
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 76360c5..a41b80e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -11055,6 +11055,14 @@
}
+void HOptimizedGraphBuilder::GenerateDebugCallbackSupportsStepping(
+ CallRuntime* call) {
+ ASSERT(call->arguments()->length() == 1);
+ // Debugging is not supported in optimized code.
+ return ast_context()->ReturnValue(graph()->GetConstantFalse());
+}
+
+
#undef CHECK_BAILOUT
#undef CHECK_ALIVE
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index c533ce3..dd1c77d 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -909,7 +909,7 @@
}
if (state_ == SWEEPING) {
- if (heap_->EnsureSweepersProgressed(static_cast<int>(bytes_to_process))) {
+ if (!heap_->mark_compact_collector()->IsConcurrentSweepingInProgress()) {
bytes_scanned_ = 0;
StartMarking(PREVENT_COMPACTION);
}
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 744f5bc..e89b5fd 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -627,14 +627,14 @@
}
ParallelSweepSpacesComplete();
sweeping_pending_ = false;
- RefillFreeLists(heap()->paged_space(OLD_DATA_SPACE));
- RefillFreeLists(heap()->paged_space(OLD_POINTER_SPACE));
+ RefillFreeList(heap()->paged_space(OLD_DATA_SPACE));
+ RefillFreeList(heap()->paged_space(OLD_POINTER_SPACE));
heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes();
heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes();
}
-intptr_t MarkCompactCollector::RefillFreeLists(PagedSpace* space) {
+void MarkCompactCollector::RefillFreeList(PagedSpace* space) {
FreeList* free_list;
if (space == heap()->old_pointer_space()) {
@@ -644,13 +644,12 @@
} else {
// Any PagedSpace might invoke RefillFreeLists, so we need to make sure
// to only refill them for old data and pointer spaces.
- return 0;
+ return;
}
intptr_t freed_bytes = space->free_list()->Concatenate(free_list);
space->AddToAccountingStats(freed_bytes);
space->DecrementUnsweptFreeBytes(freed_bytes);
- return freed_bytes;
}
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 83aa1e8..f873295 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -694,7 +694,7 @@
void WaitUntilSweepingCompleted();
- intptr_t RefillFreeLists(PagedSpace* space);
+ void RefillFreeList(PagedSpace* space);
bool AreSweeperThreadsActivated();
@@ -713,7 +713,7 @@
void MarkWeakObjectToCodeTable();
// Special case for processing weak references in a full collection. We need
- // to artifically keep AllocationSites alive for a time.
+ // to artificially keep AllocationSites alive for a time.
void MarkAllocationSite(AllocationSite* site);
private:
diff --git a/src/messages.js b/src/messages.js
index d402731..3f7a25f 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1157,19 +1157,6 @@
stackTraceLimit);
var error_string = FormatErrorString(obj);
- // The holder of this getter ('obj') may not be the receiver ('this').
- // When this getter is called the first time, we use the context values to
- // format a stack trace string and turn this accessor pair into a data
- // property (on the holder).
- var getter = function() {
- // Stack is still a raw array awaiting to be formatted.
- var result = FormatStackTrace(obj, error_string, GetStackFrames(stack));
- // Turn this accessor into a data property.
- %DefineOrRedefineDataProperty(obj, 'stack', result, NONE);
- // Release context values.
- stack = error_string = UNDEFINED;
- return result;
- };
// Set the 'stack' property on the receiver. If the receiver is the same as
// holder of this setter, the accessor pair is turned into a data property.
@@ -1182,6 +1169,21 @@
}
};
+ // The holder of this getter ('obj') may not be the receiver ('this').
+ // When this getter is called the first time, we use the context values to
+ // format a stack trace string and turn this accessor pair into a data
+ // property (on the holder).
+ var getter = function() {
+ // Stack is still a raw array awaiting to be formatted.
+ var result = FormatStackTrace(obj, error_string, GetStackFrames(stack));
+ // Replace this accessor to return result directly.
+ %DefineOrRedefineAccessorProperty(
+ obj, 'stack', function() { return result }, setter, DONT_ENUM);
+ // Release context values.
+ stack = error_string = UNDEFINED;
+ return result;
+ };
+
%DefineOrRedefineAccessorProperty(obj, 'stack', getter, setter, DONT_ENUM);
}
@@ -1320,6 +1322,15 @@
var error_string = boilerplate.name + ": " + boilerplate.message;
+ // Set the 'stack' property on the receiver. If the receiver is the same as
+ // holder of this setter, the accessor pair is turned into a data property.
+ var setter = function(v) {
+ %DefineOrRedefineDataProperty(this, 'stack', v, NONE);
+ // Tentatively clear the hidden property. If the receiver is the same as
+ // holder, we release the raw stack trace this way.
+ %GetAndClearOverflowedStackTrace(this);
+ };
+
// The raw stack trace is stored as a hidden property on the holder of this
// getter, which may not be the same as the receiver. Find the holder to
// retrieve the raw stack trace and then turn this accessor pair into a
@@ -1335,20 +1346,12 @@
if (IS_UNDEFINED(stack)) return stack;
var result = FormatStackTrace(holder, error_string, GetStackFrames(stack));
- // Replace this accessor with a data property.
- %DefineOrRedefineDataProperty(holder, 'stack', result, NONE);
+ // Replace this accessor to return result directly.
+ %DefineOrRedefineAccessorProperty(
+ holder, 'stack', function() { return result }, setter, DONT_ENUM);
return result;
};
- // Set the 'stack' property on the receiver. If the receiver is the same as
- // holder of this setter, the accessor pair is turned into a data property.
- var setter = function(v) {
- %DefineOrRedefineDataProperty(this, 'stack', v, NONE);
- // Tentatively clear the hidden property. If the receiver is the same as
- // holder, we release the raw stack trace this way.
- %GetAndClearOverflowedStackTrace(this);
- };
-
%DefineOrRedefineAccessorProperty(
boilerplate, 'stack', getter, setter, DONT_ENUM);
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index b383ea0..1608744 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -82,11 +82,6 @@
static Register registers[] = { a3, a2, a1 };
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers;
- static Representation representations[] = {
- Representation::Tagged(),
- Representation::Smi(),
- Representation::Tagged() };
- descriptor->register_param_representations_ = representations;
descriptor->deoptimization_handler_ =
Runtime::FunctionForId(
Runtime::kHiddenCreateArrayLiteralStubBailout)->entry;
@@ -230,11 +225,6 @@
descriptor->stack_parameter_count_ = a0;
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers_variable_args;
- static Representation representations[] = {
- Representation::Tagged(),
- Representation::Tagged(),
- Representation::Integer32() };
- descriptor->register_param_representations_ = representations;
}
descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
@@ -262,10 +252,6 @@
descriptor->stack_parameter_count_ = a0;
descriptor->register_param_count_ = 2;
descriptor->register_params_ = registers_variable_args;
- static Representation representations[] = {
- Representation::Tagged(),
- Representation::Integer32() };
- descriptor->register_param_representations_ = representations;
}
descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 9df3da8..8a1008d 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1850,7 +1850,17 @@
__ Push(a3, a2, a1, a0);
__ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
} else {
- FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
+ ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
+ FLAG_smi_only_arrays);
+ FastCloneShallowArrayStub::Mode mode =
+ FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
+
+ if (has_fast_elements) {
+ mode = FastCloneShallowArrayStub::CLONE_ELEMENTS;
+ }
+
+ FastCloneShallowArrayStub stub(isolate(), mode, allocation_site_mode,
+ length);
__ CallStub(&stub);
}
diff --git a/src/runtime.h b/src/runtime.h
index 3ce332b..9dca233 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -97,7 +97,6 @@
F(SetNativeFlag, 1, 1) \
F(SetInlineBuiltinFlag, 1, 1) \
F(StoreArrayLiteralElement, 5, 1) \
- F(DebugCallbackSupportsStepping, 1, 1) \
F(DebugPrepareStepInIfStepping, 1, 1) \
F(DebugPendingExceptionInPromise, 2, 1) \
F(FlattenString, 1, 1) \
@@ -707,7 +706,9 @@
F(DoubleHi, 1, 1) \
F(DoubleLo, 1, 1) \
F(MathSqrt, 1, 1) \
- F(MathLog, 1, 1)
+ F(MathLog, 1, 1) \
+ /* Debugger */ \
+ F(DebugCallbackSupportsStepping, 1, 1)
//---------------------------------------------------------------------------
diff --git a/src/spaces.cc b/src/spaces.cc
index eeb7ea8..e893f68 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -2587,33 +2587,13 @@
}
-bool PagedSpace::EnsureSweeperProgress(intptr_t size_in_bytes) {
- MarkCompactCollector* collector = heap()->mark_compact_collector();
- if (collector->AreSweeperThreadsActivated()) {
- if (collector->IsConcurrentSweepingInProgress()) {
- if (collector->RefillFreeLists(this) < size_in_bytes) {
- if (!collector->sequential_sweeping()) {
- collector->WaitUntilSweepingCompleted();
- return true;
- }
- }
- return false;
- }
- }
- return true;
-}
-
-
HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
// Allocation in this space has failed.
- // If there are unswept pages advance sweeping a bounded number of times
- // until we find a size_in_bytes contiguous piece of memory
- const int kMaxSweepingTries = 5;
- bool sweeping_complete = false;
-
- for (int i = 0; i < kMaxSweepingTries && !sweeping_complete; i++) {
- sweeping_complete = EnsureSweeperProgress(size_in_bytes);
+ // If sweeper threads are active, try to re-fill the free-lists.
+ MarkCompactCollector* collector = heap()->mark_compact_collector();
+ if (collector->IsConcurrentSweepingInProgress()) {
+ collector->RefillFreeList(this);
// Retry the free list allocation.
HeapObject* object = free_list_.Allocate(size_in_bytes);
@@ -2634,11 +2614,12 @@
return free_list_.Allocate(size_in_bytes);
}
- // Last ditch, sweep all the remaining pages to try to find space.
- if (heap()->mark_compact_collector()->IsConcurrentSweepingInProgress()) {
- heap()->mark_compact_collector()->WaitUntilSweepingCompleted();
+ // If sweeper threads are active, wait for them at that point.
+ if (collector->IsConcurrentSweepingInProgress()) {
+ collector->WaitUntilSweepingCompleted();
- // Retry the free list allocation.
+ // After waiting for the sweeper threads, there may be new free-list
+ // entries.
HeapObject* object = free_list_.Allocate(size_in_bytes);
if (object != NULL) return object;
}
diff --git a/src/spaces.h b/src/spaces.h
index 68ce26b..4fcd13c 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1914,12 +1914,6 @@
unswept_free_bytes_ = 0;
}
- // This function tries to steal size_in_bytes memory from the sweeper threads
- // free-lists. If it does not succeed stealing enough memory, it will wait
- // for the sweeper threads to finish sweeping.
- // It returns true when sweeping is completed and false otherwise.
- bool EnsureSweeperProgress(intptr_t size_in_bytes);
-
Page* FirstPage() { return anchor_.next_page(); }
Page* LastPage() { return anchor_.prev_page(); }
diff --git a/src/version.cc b/src/version.cc
index 7da193b..b322c4e 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 26
-#define BUILD_NUMBER 26
-#define PATCH_LEVEL 0
+#define BUILD_NUMBER 27
+#define PATCH_LEVEL 1
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index a11c030..85e4512 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -7659,3 +7659,34 @@
v8::Debug::SetDebugEventListener2(NULL);
CheckDebuggerUnloaded();
}
+
+
+static void DebugBreakStackTraceListener(
+ const v8::Debug::EventDetails& event_details) {
+ v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
+}
+
+
+static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Debug::DebugBreak(args.GetIsolate());
+}
+
+
+TEST(DebugBreakStackTrace) {
+ DebugLocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::Debug::SetDebugEventListener2(DebugBreakStackTraceListener);
+ v8::Handle<v8::FunctionTemplate> add_debug_break_template =
+ v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
+ v8::Handle<v8::Function> add_debug_break =
+ add_debug_break_template->GetFunction();
+ env->Global()->Set(v8_str("add_debug_break"), add_debug_break);
+
+ CompileRun("(function loop() {"
+ " for (var j = 0; j < 1000; j++) {"
+ " for (var i = 0; i < 1000; i++) {"
+ " if (i == 999) add_debug_break();"
+ " }"
+ " }"
+ "})()");
+}
diff --git a/test/mjsunit/regress/regress-3294.js b/test/mjsunit/regress/regress-3294.js
new file mode 100644
index 0000000..400e6b6
--- /dev/null
+++ b/test/mjsunit/regress/regress-3294.js
@@ -0,0 +1,8 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var e = new Error('message');
+var keys = Object.keys(e);
+e.stack;
+assertEquals(keys, Object.keys(e));