summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2013-02-08 17:17:45 -0800
committerisaacs <i@izs.me>2013-02-08 17:17:45 -0800
commit0c2e5ec840e2dc64585ea75f7539d87e5af4269e (patch)
tree43a452335e0d43a40d02498a687b0a2a61acdee4 /deps
parent8164b2fda77d9f91c6cd83d360967bf55c0bd0f1 (diff)
downloadnode-new-0c2e5ec840e2dc64585ea75f7539d87e5af4269e.tar.gz
V8: Upgrade to 3.15.11.15
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/build/common.gypi11
-rw-r--r--deps/v8/src/compiler.cc2
-rw-r--r--deps/v8/src/hydrogen.cc2
-rw-r--r--deps/v8/src/log-utils.cc3
-rw-r--r--deps/v8/src/mark-compact.cc36
-rw-r--r--deps/v8/src/mark-compact.h1
-rw-r--r--deps/v8/src/messages.js1
-rw-r--r--deps/v8/src/mips/codegen-mips.cc10
-rw-r--r--deps/v8/src/mips/lithium-codegen-mips.cc2
-rw-r--r--deps/v8/src/objects-inl.h20
-rw-r--r--deps/v8/src/objects.cc2
-rw-r--r--deps/v8/src/objects.h2
-rw-r--r--deps/v8/src/platform-posix.cc17
-rw-r--r--deps/v8/src/runtime.cc21
-rw-r--r--deps/v8/src/string.js21
-rw-r--r--deps/v8/src/v8utils.h2
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/test/cctest/test-heap.cc125
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2437.js81
-rw-r--r--deps/v8/test/mjsunit/regress/regress-2499.js40
-rw-r--r--deps/v8/test/mjsunit/regress/regress-crbug-170856.js33
21 files changed, 379 insertions, 55 deletions
diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi
index 44bebae935..e68ee15fde 100644
--- a/deps/v8/build/common.gypi
+++ b/deps/v8/build/common.gypi
@@ -160,7 +160,7 @@
[ 'v8_use_arm_eabi_hardfloat=="true"', {
'defines': [
'USE_EABI_HARDFLOAT=1',
- 'CAN_USE_VFP2_INSTRUCTIONS',
+ 'CAN_USE_VFP3_INSTRUCTIONS',
],
'target_conditions': [
['_toolset=="target"', {
@@ -399,6 +399,15 @@
}],
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
or OS=="android"', {
+ 'cflags!': [
+ '-O2',
+ '-Os',
+ ],
+ 'cflags': [
+ '-fdata-sections',
+ '-ffunction-sections',
+ '-O3',
+ ],
'conditions': [
[ 'gcc_version==44 and clang==0', {
'cflags': [
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index 5779aae81b..7e4eaa2b3b 100644
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -697,7 +697,7 @@ static bool InstallFullCode(CompilationInfo* info) {
Handle<ScopeInfo> scope_info =
ScopeInfo::Create(info->scope(), info->zone());
shared->set_scope_info(*scope_info);
- shared->set_code(*code);
+ shared->ReplaceCode(*code);
if (!function.is_null()) {
function->ReplaceCode(*code);
ASSERT(!function->IsOptimized());
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index bdca43ed52..aad9da3e75 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -8306,6 +8306,7 @@ static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
HValue* const32_minus_sa) {
if (!const32_minus_sa->IsSub()) return false;
HSub* sub = HSub::cast(const32_minus_sa);
+ if (sa != sub->right()) return false;
HValue* const32 = sub->left();
if (!const32->IsConstant() ||
HConstant::cast(const32)->Integer32Value() != 32) {
@@ -8334,6 +8335,7 @@ bool HGraphBuilder::MatchRotateRight(HValue* left,
} else {
return false;
}
+ if (shl->left() != shr->left()) return false;
if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
!ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
diff --git a/deps/v8/src/log-utils.cc b/deps/v8/src/log-utils.cc
index a66db3d931..d8d92cbe21 100644
--- a/deps/v8/src/log-utils.cc
+++ b/deps/v8/src/log-utils.cc
@@ -107,9 +107,6 @@ void Log::Initialize() {
// one character so we can escape the loop properly.
p--;
break;
- case 'p':
- stream.Add("%d", OS::GetCurrentProcessId());
- break;
case 't': {
// %t expands to the current time in milliseconds.
double time = OS::TimeCurrentMillis();
diff --git a/deps/v8/src/mark-compact.cc b/deps/v8/src/mark-compact.cc
index 8ca14db506..4e6599f09f 100644
--- a/deps/v8/src/mark-compact.cc
+++ b/deps/v8/src/mark-compact.cc
@@ -885,8 +885,8 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
if (!code_mark.Get()) {
shared->set_code(lazy_compile);
candidate->set_code(lazy_compile);
- } else if (code == lazy_compile) {
- candidate->set_code(lazy_compile);
+ } else {
+ candidate->set_code(code);
}
// We are in the middle of a GC cycle so the write barrier in the code
@@ -935,13 +935,40 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
}
+void CodeFlusher::EvictCandidate(SharedFunctionInfo* shared_info) {
+ // Make sure previous flushing decisions are revisited.
+ isolate_->heap()->incremental_marking()->RecordWrites(shared_info);
+
+ SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
+ SharedFunctionInfo* next_candidate;
+ if (candidate == shared_info) {
+ next_candidate = GetNextCandidate(shared_info);
+ shared_function_info_candidates_head_ = next_candidate;
+ ClearNextCandidate(shared_info);
+ } else {
+ while (candidate != NULL) {
+ next_candidate = GetNextCandidate(candidate);
+
+ if (next_candidate == shared_info) {
+ next_candidate = GetNextCandidate(shared_info);
+ SetNextCandidate(candidate, next_candidate);
+ ClearNextCandidate(shared_info);
+ break;
+ }
+
+ candidate = next_candidate;
+ }
+ }
+}
+
+
void CodeFlusher::EvictCandidate(JSFunction* function) {
ASSERT(!function->next_function_link()->IsUndefined());
Object* undefined = isolate_->heap()->undefined_value();
- // The function is no longer a candidate, make sure it gets visited
- // again so that previous flushing decisions are revisited.
+ // Make sure previous flushing decisions are revisited.
isolate_->heap()->incremental_marking()->RecordWrites(function);
+ isolate_->heap()->incremental_marking()->RecordWrites(function->shared());
JSFunction* candidate = jsfunction_candidates_head_;
JSFunction* next_candidate;
@@ -957,6 +984,7 @@ void CodeFlusher::EvictCandidate(JSFunction* function) {
next_candidate = GetNextCandidate(function);
SetNextCandidate(candidate, next_candidate);
ClearNextCandidate(function, undefined);
+ break;
}
candidate = next_candidate;
diff --git a/deps/v8/src/mark-compact.h b/deps/v8/src/mark-compact.h
index 9a0b014d63..8821c3df30 100644
--- a/deps/v8/src/mark-compact.h
+++ b/deps/v8/src/mark-compact.h
@@ -434,6 +434,7 @@ class CodeFlusher {
}
}
+ void EvictCandidate(SharedFunctionInfo* shared_info);
void EvictCandidate(JSFunction* function);
void ProcessCandidates() {
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index 0a50ae7861..f0c51c61f2 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -1090,6 +1090,7 @@ function captureStackTrace(obj, cons_opt) {
// with a data property as soon as the stack trace has been formatted.
var getter = function() {
var value = FormatRawStackTrace(obj, raw_stack);
+ raw_stack = void 0;
%DefineOrRedefineDataProperty(obj, 'stack', value, NONE);
return value;
};
diff --git a/deps/v8/src/mips/codegen-mips.cc b/deps/v8/src/mips/codegen-mips.cc
index 1da8089635..db313e10ee 100644
--- a/deps/v8/src/mips/codegen-mips.cc
+++ b/deps/v8/src/mips/codegen-mips.cc
@@ -529,9 +529,9 @@ void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
__ Check(eq, "Non-smi value", at, Operand(zero_reg));
__ lw(at, FieldMemOperand(string, String::kLengthOffset));
- __ Check(lt, "Index is too large", at, Operand(index));
+ __ Check(lt, "Index is too large", index, Operand(at));
- __ Check(ge, "Index is negative", index, Operand(Smi::FromInt(0)));
+ __ Check(ge, "Index is negative", index, Operand(zero_reg));
__ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
__ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
@@ -539,9 +539,9 @@ void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
__ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
- __ Check(eq, "Unexpected string type", at,
- Operand(encoding == String::ONE_BYTE_ENCODING
- ? one_byte_seq_type : two_byte_seq_type));
+ __ Subu(at, at, Operand(encoding == String::ONE_BYTE_ENCODING
+ ? one_byte_seq_type : two_byte_seq_type));
+ __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
}
__ Addu(at,
diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc
index fd7af9f0f5..cc589e0b30 100644
--- a/deps/v8/src/mips/lithium-codegen-mips.cc
+++ b/deps/v8/src/mips/lithium-codegen-mips.cc
@@ -4016,7 +4016,7 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
__ Branch(&not_applicable, ne, scratch, Operand(from_map));
__ li(new_map_reg, Operand(to_map));
- if (IsFastSmiElementsKind(from_kind) && IsFastObjectElementsKind(to_kind)) {
+ if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
__ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
// Write barrier.
__ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index 67db5b4944..1d9c87f0ef 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -4368,6 +4368,19 @@ void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
}
+void SharedFunctionInfo::ReplaceCode(Code* value) {
+ // If the GC metadata field is already used then the function was
+ // enqueued as a code flushing candidate and we remove it now.
+ if (code()->gc_metadata() != NULL) {
+ CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
+ flusher->EvictCandidate(this);
+ }
+
+ ASSERT(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
+ set_code(value);
+}
+
+
ScopeInfo* SharedFunctionInfo::scope_info() {
return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
}
@@ -4955,13 +4968,6 @@ void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
}
-void JSRegExp::ResetLastIndex() {
- InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
- Smi::FromInt(0),
- SKIP_WRITE_BARRIER); // It's a Smi.
-}
-
-
ElementsKind JSObject::GetElementsKind() {
ElementsKind kind = map()->elements_kind();
#if DEBUG
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 885a5dd8b2..126d1e0fd7 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -8562,7 +8562,7 @@ void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
// old code, we have to replace it. We should try to avoid this
// altogether because it flushes valuable type feedback by
// effectively resetting all IC state.
- set_code(recompiled);
+ ReplaceCode(recompiled);
}
ASSERT(has_deoptimization_support());
}
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 6c9b31b937..0be263a488 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -5429,6 +5429,7 @@ class SharedFunctionInfo: public HeapObject {
// [code]: Function code.
DECL_ACCESSORS(code, Code)
+ inline void ReplaceCode(Code* code);
// [optimized_code_map]: Map from native context to optimized code
// and a shared literals array or Smi 0 if none.
@@ -6648,7 +6649,6 @@ class JSRegExp: public JSObject {
inline Object* DataAtUnchecked(int index);
inline void SetDataAtUnchecked(int index, Object* value, Heap* heap);
inline Type TypeTagUnchecked();
- inline void ResetLastIndex();
static int code_index(bool is_ascii) {
if (is_ascii) {
diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc
index e652a083cd..0016d59d3a 100644
--- a/deps/v8/src/platform-posix.cc
+++ b/deps/v8/src/platform-posix.cc
@@ -109,20 +109,11 @@ void* OS::GetRandomMmapAddr() {
raw_addr &= V8_UINT64_C(0x3ffffffff000);
#else
uint32_t raw_addr = V8::RandomPrivate(isolate);
-
- // For our 32-bit mmap() hint, we pick a random address in the bottom
- // half of the top half of the address space (that is, the third quarter).
- // Because we do not MAP_FIXED, this will be treated only as a hint -- the
- // system will not fail to mmap() because something else happens to already
- // be mapped at our random address. We deliberately set the hint high enough
- // to get well above the system's break (that is, the heap); systems will
- // either try the hint and if that fails move higher (MacOS and other BSD
- // derivatives) or try the hint and if that fails allocate as if there were
- // no hint at all (Linux, Solaris, illumos and derivatives). The high hint
- // prevents the break from getting hemmed in at low values, ceding half of
- // the address space to the system heap.
+ // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
+ // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
+ // 10.6 and 10.7.
raw_addr &= 0x3ffff000;
- raw_addr += 0x80000000;
+ raw_addr += 0x20000000;
#endif
return reinterpret_cast<void*>(raw_addr);
}
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 446443148d..09ca04706d 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -1098,14 +1098,15 @@ static MaybeObject* GetOwnProperty(Isolate* isolate,
PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
if (attrs == ABSENT) return heap->undefined_value();
- AccessorPair* accessors = obj->GetLocalPropertyAccessorPair(*name);
+ AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
+ Handle<AccessorPair> accessors(raw_accessors, isolate);
Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
- elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(accessors != NULL));
+ elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
- if (accessors == NULL) {
+ if (raw_accessors == NULL) {
elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
// GetProperty does access check.
Handle<Object> value = GetProperty(obj, name);
@@ -1790,7 +1791,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
regexp->InObjectPropertyAtPut(
JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
- regexp->ResetLastIndex();
+ regexp->InObjectPropertyAtPut(
+ JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
return regexp;
}
@@ -2145,7 +2147,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
// target function to undefined. SetCode is only used for built-in
// constructors like String, Array, and Object, and some web code
// doesn't like seeing source code for constructors.
- target_shared->set_code(source_shared->code());
+ target_shared->ReplaceCode(source_shared->code());
target_shared->set_scope_info(source_shared->scope_info());
target_shared->set_length(source_shared->length());
target_shared->set_formal_parameter_count(
@@ -2903,8 +2905,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString(
int matches = indices.length();
if (matches == 0) {
- pattern_regexp->ResetLastIndex();
- return *subject;
+ return isolate->heap()->undefined_value();
}
// Detect integer overflow.
@@ -3005,8 +3006,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
if (global_cache.HasException()) return Failure::Exception();
- regexp->ResetLastIndex();
- return *subject;
+ return isolate->heap()->undefined_value();
}
// Guessing the number of parts that the final result string is built
@@ -3104,8 +3104,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
if (global_cache.HasException()) return Failure::Exception();
- regexp->ResetLastIndex();
- return *subject;
+ return isolate->heap()->undefined_value();
}
int start = current_match[0];
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index d9ca035fb5..eb9aa35486 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -194,6 +194,7 @@ function StringMatch(regexp) {
// lastMatchInfo is defined in regexp.js.
var result = %StringMatch(subject, regexp, lastMatchInfo);
if (result !== null) lastMatchInfoOverride = null;
+ regexp.lastIndex = 0;
return result;
}
// Non-regexp argument.
@@ -244,10 +245,16 @@ function StringReplace(search, replace) {
}
} else {
if (lastMatchInfoOverride == null) {
- return %StringReplaceRegExpWithString(subject,
- search,
- TO_STRING_INLINE(replace),
- lastMatchInfo);
+ var answer = %StringReplaceRegExpWithString(subject,
+ search,
+ TO_STRING_INLINE(replace),
+ lastMatchInfo);
+ if (IS_UNDEFINED(answer)) { // No match. Return subject string.
+ search.lastIndex = 0;
+ return subject;
+ }
+ if (search.global) search.lastIndex = 0;
+ return answer;
} else {
// We use this hack to detect whether StringReplaceRegExpWithString
// found at least one hit. In that case we need to remove any
@@ -258,11 +265,17 @@ function StringReplace(search, replace) {
search,
TO_STRING_INLINE(replace),
lastMatchInfo);
+ if (IS_UNDEFINED(answer)) { // No match. Return subject string.
+ search.lastIndex = 0;
+ lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject;
+ return subject;
+ }
if (%_IsSmi(lastMatchInfo[LAST_SUBJECT_INDEX])) {
lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject;
} else {
lastMatchInfoOverride = null;
}
+ if (search.global) search.lastIndex = 0;
return answer;
}
}
diff --git a/deps/v8/src/v8utils.h b/deps/v8/src/v8utils.h
index 111abdf8b8..9072b4e285 100644
--- a/deps/v8/src/v8utils.h
+++ b/deps/v8/src/v8utils.h
@@ -209,8 +209,6 @@ INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
template <typename sourcechar, typename sinkchar>
void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
- ASSERT(chars >= 0);
- if (chars == 0) return;
sinkchar* limit = dest + chars;
#ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*dest) == sizeof(*src)) {
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 7d317418d8..31d93d6780 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 15
#define BUILD_NUMBER 11
-#define PATCH_LEVEL 10
+#define PATCH_LEVEL 15
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index 93ac211687..533a1c3ef1 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -2575,3 +2575,128 @@ TEST(Regress159140) {
// Unoptimized code is missing and the deoptimizer will go ballistic.
CompileRun("g('bozo');");
}
+
+
+TEST(Regress169209) {
+ i::FLAG_allow_natives_syntax = true;
+ i::FLAG_flush_code_incrementally = true;
+ InitializeVM();
+ v8::HandleScope scope;
+
+ // Perform one initial GC to enable code flushing.
+ HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
+
+ // Prepare a shared function info eligible for code flushing for which
+ // the unoptimized code will be replaced during optimization.
+ Handle<SharedFunctionInfo> shared1;
+ {
+ HandleScope inner_scope;
+ CompileRun("function f() { return 'foobar'; }"
+ "function g(x) { if (x) f(); }"
+ "f();"
+ "g(false);"
+ "g(false);");
+
+ Handle<JSFunction> f =
+ v8::Utils::OpenHandle(
+ *v8::Handle<v8::Function>::Cast(
+ v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
+ CHECK(f->is_compiled());
+ const int kAgingThreshold = 6;
+ for (int i = 0; i < kAgingThreshold; i++) {
+ f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
+ }
+
+ shared1 = inner_scope.CloseAndEscape(handle(f->shared(), ISOLATE));
+ }
+
+ // Prepare a shared function info eligible for code flushing that will
+ // represent the dangling tail of the candidate list.
+ Handle<SharedFunctionInfo> shared2;
+ {
+ HandleScope inner_scope;
+ CompileRun("function flushMe() { return 0; }"
+ "flushMe(1);");
+
+ Handle<JSFunction> f =
+ v8::Utils::OpenHandle(
+ *v8::Handle<v8::Function>::Cast(
+ v8::Context::GetCurrent()->Global()->Get(v8_str("flushMe"))));
+ CHECK(f->is_compiled());
+ const int kAgingThreshold = 6;
+ for (int i = 0; i < kAgingThreshold; i++) {
+ f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
+ }
+
+ shared2 = inner_scope.CloseAndEscape(handle(f->shared(), ISOLATE));
+ }
+
+ // Simulate incremental marking and collect code flushing candidates.
+ SimulateIncrementalMarking();
+ CHECK(shared1->code()->gc_metadata() != NULL);
+
+ // Optimize function and make sure the unoptimized code is replaced.
+#ifdef DEBUG
+ FLAG_stop_at = "f";
+#endif
+ CompileRun("%OptimizeFunctionOnNextCall(g);"
+ "g(false);");
+
+ // Finish garbage collection cycle.
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ CHECK(shared1->code()->gc_metadata() == NULL);
+}
+
+
+TEST(Regress168801) {
+ i::FLAG_always_compact = true;
+ i::FLAG_cache_optimized_code = false;
+ i::FLAG_allow_natives_syntax = true;
+ i::FLAG_flush_code_incrementally = true;
+ InitializeVM();
+ v8::HandleScope scope;
+
+ // Perform one initial GC to enable code flushing.
+ HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
+
+ // Ensure the code ends up on an evacuation candidate.
+ SimulateFullSpace(HEAP->code_space());
+
+ // Prepare an unoptimized function that is eligible for code flushing.
+ Handle<JSFunction> function;
+ {
+ HandleScope inner_scope;
+ CompileRun("function mkClosure() {"
+ " return function(x) { return x + 1; };"
+ "}"
+ "var f = mkClosure();"
+ "f(1); f(2);");
+
+ Handle<JSFunction> f =
+ v8::Utils::OpenHandle(
+ *v8::Handle<v8::Function>::Cast(
+ v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
+ CHECK(f->is_compiled());
+ const int kAgingThreshold = 6;
+ for (int i = 0; i < kAgingThreshold; i++) {
+ f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2));
+ }
+
+ function = inner_scope.CloseAndEscape(handle(*f, ISOLATE));
+ }
+
+ // Simulate incremental marking so that unoptimized function is enqueued as a
+ // candidate for code flushing. The shared function info however will not be
+ // explicitly enqueued.
+ SimulateIncrementalMarking();
+
+ // Now optimize the function so that it is taken off the candidate list.
+ {
+ HandleScope inner_scope;
+ CompileRun("%OptimizeFunctionOnNextCall(f); f(3);");
+ }
+
+ // This cycle will bust the heap and subsequent cycles will go ballistic.
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-2437.js b/deps/v8/test/mjsunit/regress/regress-2437.js
index 06b69b23db..c82293ae32 100644
--- a/deps/v8/test/mjsunit/regress/regress-2437.js
+++ b/deps/v8/test/mjsunit/regress/regress-2437.js
@@ -25,6 +25,14 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Summary of the spec: lastIndex is reset to 0 if
+// - a regexp fails to match, regardless of global or non-global.
+// - a global regexp is used in a function that returns multiple results,
+// such as String.prototype.replace or String.prototype.match, since it
+// repeats the regexp until it fails to match.
+// Otherwise lastIndex is only set when a global regexp matches, to the index
+// after the match.
+
// Test Regexp.prototype.exec
r = /a/;
r.lastIndex = 1;
@@ -73,3 +81,76 @@ r.lastIndex = 1;
"zzzz".replace(r, function() { return ""; });
assertEquals(0, r.lastIndex);
+// Regexp functions that returns multiple results:
+// A global regexp always resets lastIndex regardless of whether it matches.
+r = /a/g;
+r.lastIndex = -1;
+"0123abcd".replace(r, "x");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = -1;
+"01234567".replace(r, "x");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = -1;
+"0123abcd".match(r);
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = -1;
+"01234567".match(r);
+assertEquals(0, r.lastIndex);
+
+// A non-global regexp resets lastIndex iff it does not match.
+r = /a/;
+r.lastIndex = -1;
+"0123abcd".replace(r, "x");
+assertEquals(-1, r.lastIndex);
+
+r.lastIndex = -1;
+"01234567".replace(r, "x");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = -1;
+"0123abcd".match(r);
+assertEquals(-1, r.lastIndex);
+
+r.lastIndex = -1;
+"01234567".match(r);
+assertEquals(0, r.lastIndex);
+
+// Also test RegExp.prototype.exec and RegExp.prototype.test
+r = /a/g;
+r.lastIndex = 1;
+r.exec("01234567");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = 1;
+r.exec("0123abcd");
+assertEquals(5, r.lastIndex);
+
+r = /a/;
+r.lastIndex = 1;
+r.exec("01234567");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = 1;
+r.exec("0123abcd");
+assertEquals(1, r.lastIndex);
+
+r = /a/g;
+r.lastIndex = 1;
+r.test("01234567");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = 1;
+r.test("0123abcd");
+assertEquals(5, r.lastIndex);
+
+r = /a/;
+r.lastIndex = 1;
+r.test("01234567");
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = 1;
+r.test("0123abcd");
+assertEquals(1, r.lastIndex);
diff --git a/deps/v8/test/mjsunit/regress/regress-2499.js b/deps/v8/test/mjsunit/regress/regress-2499.js
new file mode 100644
index 0000000000..52aad874db
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-2499.js
@@ -0,0 +1,40 @@
+// Copyright 2013 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.
+
+// Flags: --allow-natives-syntax
+
+function foo(word, nBits) {
+ return (word[1] >>> nBits) | (word[0] << (32 - nBits));
+}
+
+word = [0x1001, 0];
+
+var expected = foo(word, 1);
+foo(word, 1);
+%OptimizeFunctionOnNextCall(foo);
+var optimized = foo(word, 1);
+assertEquals(expected, optimized)
diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-170856.js b/deps/v8/test/mjsunit/regress/regress-crbug-170856.js
new file mode 100644
index 0000000000..2e73b12caa
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-crbug-170856.js
@@ -0,0 +1,33 @@
+// Copyright 2013 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.
+
+r = new RegExp("a");
+for (var i = 0; i < 100; i++) {
+ r["abc" + i] = i;
+}
+"zzzz".replace(r, "");
+assertEquals(0, r.lastIndex);