Version 3.11.3
Disable optimization for functions that have scopes that cannot be reconstructed from the context chain. (issue 2071)
Define V8_EXPORT to nothing for clients of v8. (Chromium issue 90078)
Correctly check for native error objects. (Chromium issue 2138)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@11594 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 4f75720..979c9c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2012-05-18: Version 3.11.3
+
+ Disable optimization for functions that have scopes that cannot be
+ reconstructed from the context chain. (issue 2071)
+
+ Define V8_EXPORT to nothing for clients of v8. (Chromium issue 90078)
+
+ Correctly check for native error objects. (Chromium issue 2138)
+
+ Performance and stability improvements on all platforms.
+
+
2012-05-16: Version 3.11.2
Revert r11496. (Chromium issue 128146)
diff --git a/SConstruct b/SConstruct
index b0d1344..ebce7ff 100644
--- a/SConstruct
+++ b/SConstruct
@@ -101,14 +101,14 @@
'os:linux': {
'CCFLAGS': ['-ansi'] + GCC_EXTRA_CCFLAGS,
'library:shared': {
- 'CPPDEFINES': ['V8_SHARED'],
+ 'CPPDEFINES': ['V8_SHARED', 'BUILDING_V8_SHARED'],
'LIBS': ['pthread']
}
},
'os:macos': {
'CCFLAGS': ['-ansi', '-mmacosx-version-min=10.4'],
'library:shared': {
- 'CPPDEFINES': ['V8_SHARED']
+ 'CPPDEFINES': ['V8_SHARED', 'BUILDING_V8_SHARED'],
}
},
'os:freebsd': {
diff --git a/include/v8.h b/include/v8.h
index 9024531..d31ef54 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -62,11 +62,13 @@
#else // _WIN32
-// Setup for Linux shared library export. There is no need to distinguish
-// between building or using the V8 shared library, but we should not
-// export symbols when we are building a static library.
+// Setup for Linux shared library export.
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED)
+#ifdef BUILDING_V8_SHARED
#define V8EXPORT __attribute__ ((visibility("default")))
+#else
+#define V8EXPORT
+#endif
#else // defined(__GNUC__) && (__GNUC__ >= 4)
#define V8EXPORT
#endif // defined(__GNUC__) && (__GNUC__ >= 4)
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 9f44872..3c8df29 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -3466,104 +3466,6 @@
}
-void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
- VisitForStackValue(args->at(2));
- Label done;
- Label slow_case;
- Register object = r0;
- Register index1 = r1;
- Register index2 = r2;
- Register elements = r3;
- Register scratch1 = r4;
- Register scratch2 = r5;
-
- __ ldr(object, MemOperand(sp, 2 * kPointerSize));
- // Fetch the map and check if array is in fast case.
- // Check that object doesn't require security checks and
- // has no indexed interceptor.
- __ CompareObjectType(object, scratch1, scratch2, JS_ARRAY_TYPE);
- __ b(ne, &slow_case);
- // Map is now in scratch1.
-
- __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
- __ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
- __ b(ne, &slow_case);
-
- // Check the object's elements are in fast case and writable.
- __ ldr(elements, FieldMemOperand(object, JSObject::kElementsOffset));
- __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
- __ cmp(scratch1, ip);
- __ b(ne, &slow_case);
-
- // Check that both indices are smis.
- __ ldr(index1, MemOperand(sp, 1 * kPointerSize));
- __ ldr(index2, MemOperand(sp, 0));
- __ JumpIfNotBothSmi(index1, index2, &slow_case);
-
- // Check that both indices are valid.
- __ ldr(scratch1, FieldMemOperand(object, JSArray::kLengthOffset));
- __ cmp(scratch1, index1);
- __ cmp(scratch1, index2, hi);
- __ b(ls, &slow_case);
-
- // Bring the address of the elements into index1 and index2.
- __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- __ add(index1,
- scratch1,
- Operand(index1, LSL, kPointerSizeLog2 - kSmiTagSize));
- __ add(index2,
- scratch1,
- Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize));
-
- // Swap elements.
- __ ldr(scratch1, MemOperand(index1, 0));
- __ ldr(scratch2, MemOperand(index2, 0));
- __ str(scratch1, MemOperand(index2, 0));
- __ str(scratch2, MemOperand(index1, 0));
-
- Label no_remembered_set;
- __ CheckPageFlag(elements,
- scratch1,
- 1 << MemoryChunk::SCAN_ON_SCAVENGE,
- ne,
- &no_remembered_set);
- // Possible optimization: do a check that both values are Smis
- // (or them and test against Smi mask.)
-
- // We are swapping two objects in an array and the incremental marker never
- // pauses in the middle of scanning a single object. Therefore the
- // incremental marker is not disturbed, so we don't need to call the
- // RecordWrite stub that notifies the incremental marker.
- __ RememberedSetHelper(elements,
- index1,
- scratch2,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
- __ RememberedSetHelper(elements,
- index2,
- scratch2,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
-
- __ bind(&no_remembered_set);
- // We are done. Drop elements from the stack, and return undefined.
- __ Drop(3);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- __ jmp(&done);
-
- __ bind(&slow_case);
- __ CallRuntime(Runtime::kSwapElements, 3);
-
- __ bind(&done);
- context()->Plug(r0);
-}
-
-
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length());
diff --git a/src/array.js b/src/array.js
index 9f2c8de..a1cc5b6 100644
--- a/src/array.js
+++ b/src/array.js
@@ -827,7 +827,8 @@
var element = a[i];
var order = %_CallFunction(receiver, element, pivot, comparefn);
if (order < 0) {
- %_SwapElements(a, i, low_end);
+ a[i] = a[low_end];
+ a[low_end] = element;
low_end++;
} else if (order > 0) {
do {
@@ -836,9 +837,12 @@
var top_elem = a[high_start];
order = %_CallFunction(receiver, top_elem, pivot, comparefn);
} while (order > 0);
- %_SwapElements(a, i, high_start);
+ a[i] = a[high_start];
+ a[high_start] = element;
if (order < 0) {
- %_SwapElements(a, i, low_end);
+ element = a[i];
+ a[i] = a[low_end];
+ a[low_end] = element;
low_end++;
}
}
diff --git a/src/compiler.cc b/src/compiler.cc
index c9c2480..ecac5cb 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -118,7 +118,7 @@
FLAG_crankshaft &&
!function()->flags()->Contains(kDontSelfOptimize) &&
!function()->flags()->Contains(kDontOptimize) &&
- function()->scope()->allows_lazy_recompilation() &&
+ function()->scope()->AllowsLazyRecompilation() &&
(shared_info().is_null() || !shared_info()->optimization_disabled());
}
diff --git a/src/d8.cc b/src/d8.cc
index adbe550..ddd4100 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -26,7 +26,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifdef USING_V8_SHARED // Defined when linking against shared lib on Windows.
+// Defined when linking against shared lib on Windows.
+#if defined(USING_V8_SHARED) && !defined(V8_SHARED)
#define V8_SHARED
#endif
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index b8794c0..9b1df4e 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -314,7 +314,8 @@
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
code->set_optimizable(info->IsOptimizable() &&
- !info->function()->flags()->Contains(kDontOptimize));
+ !info->function()->flags()->Contains(kDontOptimize) &&
+ info->function()->scope()->AllowsLazyRecompilation());
cgen.PopulateDeoptimizationData(code);
cgen.PopulateTypeFeedbackInfo(code);
cgen.PopulateTypeFeedbackCells(code);
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 3be001e..4e9afc6 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -8135,14 +8135,6 @@
}
-// Fast swapping of elements. Takes three expressions, the object and two
-// indices. This should only be used if the indices are known to be
-// non-negative and within bounds of the elements array at the call site.
-void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
- return Bailout("inlined runtime function: SwapElements");
-}
-
-
// Fast call for custom callbacks.
void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
// 1 ~ The function to call is not itself an argument to the call.
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index 901e38b..d153e18 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -175,7 +175,7 @@
// Read current padding counter and skip corresponding number of words.
__ pop(unused_reg);
// We divide stored value by 2 (untagging) and multiply it by word's size.
- STATIC_ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiShiftSize == 0);
__ lea(esp, Operand(esp, unused_reg, times_half_pointer_size, 0));
// Get rid of the internal frame.
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 10fe77b..266afce 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -3405,99 +3405,6 @@
}
-void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
- VisitForStackValue(args->at(2));
- Label done;
- Label slow_case;
- Register object = eax;
- Register index_1 = ebx;
- Register index_2 = ecx;
- Register elements = edi;
- Register temp = edx;
- __ mov(object, Operand(esp, 2 * kPointerSize));
- // Fetch the map and check if array is in fast case.
- // Check that object doesn't require security checks and
- // has no indexed interceptor.
- __ CmpObjectType(object, JS_ARRAY_TYPE, temp);
- __ j(not_equal, &slow_case);
- __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
- KeyedLoadIC::kSlowCaseBitFieldMask);
- __ j(not_zero, &slow_case);
-
- // Check the object's elements are in fast case and writable.
- __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
- __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
- Immediate(isolate()->factory()->fixed_array_map()));
- __ j(not_equal, &slow_case);
-
- // Check that both indices are smis.
- __ mov(index_1, Operand(esp, 1 * kPointerSize));
- __ mov(index_2, Operand(esp, 0));
- __ mov(temp, index_1);
- __ or_(temp, index_2);
- __ JumpIfNotSmi(temp, &slow_case);
-
- // Check that both indices are valid.
- __ mov(temp, FieldOperand(object, JSArray::kLengthOffset));
- __ cmp(temp, index_1);
- __ j(below_equal, &slow_case);
- __ cmp(temp, index_2);
- __ j(below_equal, &slow_case);
-
- // Bring addresses into index1 and index2.
- __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
- __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
-
- // Swap elements. Use object and temp as scratch registers.
- __ mov(object, Operand(index_1, 0));
- __ mov(temp, Operand(index_2, 0));
- __ mov(Operand(index_2, 0), object);
- __ mov(Operand(index_1, 0), temp);
-
- Label no_remembered_set;
- __ CheckPageFlag(elements,
- temp,
- 1 << MemoryChunk::SCAN_ON_SCAVENGE,
- not_zero,
- &no_remembered_set,
- Label::kNear);
- // Possible optimization: do a check that both values are Smis
- // (or them and test against Smi mask.)
-
- // We are swapping two objects in an array and the incremental marker never
- // pauses in the middle of scanning a single object. Therefore the
- // incremental marker is not disturbed, so we don't need to call the
- // RecordWrite stub that notifies the incremental marker.
- __ RememberedSetHelper(elements,
- index_1,
- temp,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
- __ RememberedSetHelper(elements,
- index_2,
- temp,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
-
- __ bind(&no_remembered_set);
-
- // We are done. Drop elements from the stack, and return undefined.
- __ add(esp, Immediate(3 * kPointerSize));
- __ mov(eax, isolate()->factory()->undefined_value());
- __ jmp(&done);
-
- __ bind(&slow_case);
- __ CallRuntime(Runtime::kSwapElements, 3);
-
- __ bind(&done);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length());
diff --git a/src/messages.js b/src/messages.js
index d813df9..ab71936 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -61,18 +61,21 @@
// To check if something is a native error we need to check the
-// concrete native error types. It is not enough to check "obj
-// instanceof $Error" because user code can replace
-// NativeError.prototype.__proto__. User code cannot replace
-// NativeError.prototype though and therefore this is a safe test.
+// concrete native error types. It is not sufficient to use instanceof
+// since it possible to create an object that has Error.prototype on
+// its prototype chain. This is the case for DOMException for example.
function IsNativeErrorObject(obj) {
- return (obj instanceof $Error) ||
- (obj instanceof $EvalError) ||
- (obj instanceof $RangeError) ||
- (obj instanceof $ReferenceError) ||
- (obj instanceof $SyntaxError) ||
- (obj instanceof $TypeError) ||
- (obj instanceof $URIError);
+ switch (%_ClassOf(obj)) {
+ case 'Error':
+ case 'EvalError':
+ case 'RangeError':
+ case 'ReferenceError':
+ case 'SyntaxError':
+ case 'TypeError':
+ case 'URIError':
+ return true;
+ }
+ return false;
}
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 4ffd0ea..7be5056 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -3500,104 +3500,6 @@
}
-void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
- VisitForStackValue(args->at(2));
- Label done;
- Label slow_case;
- Register object = a0;
- Register index1 = a1;
- Register index2 = a2;
- Register elements = a3;
- Register scratch1 = t0;
- Register scratch2 = t1;
-
- __ lw(object, MemOperand(sp, 2 * kPointerSize));
- // Fetch the map and check if array is in fast case.
- // Check that object doesn't require security checks and
- // has no indexed interceptor.
- __ GetObjectType(object, scratch1, scratch2);
- __ Branch(&slow_case, ne, scratch2, Operand(JS_ARRAY_TYPE));
- // Map is now in scratch1.
-
- __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
- __ And(scratch2, scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
- __ Branch(&slow_case, ne, scratch2, Operand(zero_reg));
-
- // Check the object's elements are in fast case and writable.
- __ lw(elements, FieldMemOperand(object, JSObject::kElementsOffset));
- __ lw(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
- __ LoadRoot(scratch2, Heap::kFixedArrayMapRootIndex);
- __ Branch(&slow_case, ne, scratch1, Operand(scratch2));
-
- // Check that both indices are smis.
- __ lw(index1, MemOperand(sp, 1 * kPointerSize));
- __ lw(index2, MemOperand(sp, 0));
- __ JumpIfNotBothSmi(index1, index2, &slow_case);
-
- // Check that both indices are valid.
- Label not_hi;
- __ lw(scratch1, FieldMemOperand(object, JSArray::kLengthOffset));
- __ Branch(&slow_case, ls, scratch1, Operand(index1));
- __ Branch(¬_hi, NegateCondition(hi), scratch1, Operand(index1));
- __ Branch(&slow_case, ls, scratch1, Operand(index2));
- __ bind(¬_hi);
-
- // Bring the address of the elements into index1 and index2.
- __ Addu(scratch1, elements,
- Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- __ sll(index1, index1, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(index1, scratch1, index1);
- __ sll(index2, index2, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(index2, scratch1, index2);
-
- // Swap elements.
- __ lw(scratch1, MemOperand(index1, 0));
- __ lw(scratch2, MemOperand(index2, 0));
- __ sw(scratch1, MemOperand(index2, 0));
- __ sw(scratch2, MemOperand(index1, 0));
-
- Label no_remembered_set;
- __ CheckPageFlag(elements,
- scratch1,
- 1 << MemoryChunk::SCAN_ON_SCAVENGE,
- ne,
- &no_remembered_set);
- // Possible optimization: do a check that both values are Smis
- // (or them and test against Smi mask).
-
- // We are swapping two objects in an array and the incremental marker never
- // pauses in the middle of scanning a single object. Therefore the
- // incremental marker is not disturbed, so we don't need to call the
- // RecordWrite stub that notifies the incremental marker.
- __ RememberedSetHelper(elements,
- index1,
- scratch2,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
- __ RememberedSetHelper(elements,
- index2,
- scratch2,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
-
- __ bind(&no_remembered_set);
- // We are done. Drop elements from the stack, and return undefined.
- __ Drop(3);
- __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
- __ jmp(&done);
-
- __ bind(&slow_case);
- __ CallRuntime(Runtime::kSwapElements, 3);
-
- __ bind(&done);
- context()->Plug(v0);
-}
-
-
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length());
diff --git a/src/runtime.cc b/src/runtime.cc
index 0b80eff..a42f90c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10026,36 +10026,6 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SwapElements) {
- HandleScope handle_scope(isolate);
-
- ASSERT_EQ(3, args.length());
-
- CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- Handle<Object> key1 = args.at<Object>(1);
- Handle<Object> key2 = args.at<Object>(2);
-
- uint32_t index1, index2;
- if (!key1->ToArrayIndex(&index1)
- || !key2->ToArrayIndex(&index2)) {
- return isolate->ThrowIllegalOperation();
- }
-
- Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
- Handle<Object> tmp1 = Object::GetElement(jsobject, index1);
- RETURN_IF_EMPTY_HANDLE(isolate, tmp1);
- Handle<Object> tmp2 = Object::GetElement(jsobject, index2);
- RETURN_IF_EMPTY_HANDLE(isolate, tmp2);
-
- RETURN_IF_EMPTY_HANDLE(
- isolate, JSObject::SetElement(jsobject, index1, tmp2, NONE, kStrictMode));
- RETURN_IF_EMPTY_HANDLE(
- isolate, JSObject::SetElement(jsobject, index2, tmp1, NONE, kStrictMode));
-
- return isolate->heap()->undefined_value();
-}
-
-
// Returns an array that tells you where in the [0, length) interval an array
// might have elements. Can either return keys (positive integers) or
// intervals (pair of a negative integer (-start-1) followed by a
diff --git a/src/runtime.h b/src/runtime.h
index a09d9cc..83991bb 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -272,7 +272,6 @@
F(GetArrayKeys, 2, 1) \
F(MoveArrayContents, 2, 1) \
F(EstimateNumberOfElements, 1, 1) \
- F(SwapElements, 3, 1) \
\
/* Getters and Setters */ \
F(LookupAccessor, 3, 1) \
@@ -536,8 +535,7 @@
F(RegExpExec, 4, 1) \
F(RegExpConstructResult, 3, 1) \
F(GetFromCache, 2, 1) \
- F(NumberToString, 1, 1) \
- F(SwapElements, 3, 1)
+ F(NumberToString, 1, 1)
//---------------------------------------------------------------------------
diff --git a/src/scopes.cc b/src/scopes.cc
index 6f6032a..2c61a75 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -658,6 +658,26 @@
}
+bool Scope::AllowsLazyRecompilation() const {
+ return !force_eager_compilation_ &&
+ !TrivialDeclarationScopesBeforeWithScope();
+}
+
+
+bool Scope::TrivialDeclarationScopesBeforeWithScope() const {
+ Scope* outer = outer_scope_;
+ if (outer == NULL) return false;
+ outer = outer->DeclarationScope();
+ while (outer != NULL) {
+ if (outer->is_with_scope()) return true;
+ if (outer->is_declaration_scope() && outer->num_heap_slots() > 0)
+ return false;
+ outer = outer->outer_scope_;
+ }
+ return false;
+}
+
+
int Scope::ContextChainLength(Scope* scope) {
int n = 0;
for (Scope* s = this; s != scope; s = s->outer_scope_) {
diff --git a/src/scopes.h b/src/scopes.h
index e1a658a..be6705b 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -362,13 +362,16 @@
bool AllowsLazyCompilation() const;
// True if we can lazily recompile functions with this scope.
- bool allows_lazy_recompilation() const {
- return !force_eager_compilation_;
- }
+ bool AllowsLazyRecompilation() const;
// True if the outer context of this scope is always the global context.
bool HasTrivialOuterContext() const;
+ // True if this scope is inside a with scope and all declaration scopes
+ // between them have empty contexts. Such declaration scopes become
+ // invisible during scope info deserialization.
+ bool TrivialDeclarationScopesBeforeWithScope() const;
+
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
diff --git a/src/version.cc b/src/version.cc
index 6162ea4..7c33df1 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 11
-#define BUILD_NUMBER 2
+#define BUILD_NUMBER 3
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 94a50eb..1b29e58 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -91,7 +91,7 @@
rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
}
-const bool Debug::FramePaddingLayout::kIsSupported = false;
+const bool Debug::FramePaddingLayout::kIsSupported = true;
#define __ ACCESS_MASM(masm)
@@ -105,6 +105,12 @@
{
FrameScope scope(masm, StackFrame::INTERNAL);
+ // Load padding words on stack.
+ for (int i = 0; i < Debug::FramePaddingLayout::kInitialSize; i++) {
+ __ Push(Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue));
+ }
+ __ Push(Smi::FromInt(Debug::FramePaddingLayout::kInitialSize));
+
// Store the registers containing live values on the expression stack to
// make sure that these are correctly updated during GC. Non object values
// are stored as as two smis causing it to be untouched by GC.
@@ -159,6 +165,11 @@
}
}
+ // Read current padding counter and skip corresponding number of words.
+ __ pop(kScratchRegister);
+ __ SmiToInteger32(kScratchRegister, kScratchRegister);
+ __ lea(rsp, Operand(rsp, kScratchRegister, times_pointer_size, 0));
+
// Get rid of the internal frame.
}
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index a6c4c99..974269e 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -3360,102 +3360,6 @@
}
-void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
- VisitForStackValue(args->at(2));
- Label done;
- Label slow_case;
- Register object = rax;
- Register index_1 = rbx;
- Register index_2 = rcx;
- Register elements = rdi;
- Register temp = rdx;
- __ movq(object, Operand(rsp, 2 * kPointerSize));
- // Fetch the map and check if array is in fast case.
- // Check that object doesn't require security checks and
- // has no indexed interceptor.
- __ CmpObjectType(object, JS_ARRAY_TYPE, temp);
- __ j(not_equal, &slow_case);
- __ testb(FieldOperand(temp, Map::kBitFieldOffset),
- Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
- __ j(not_zero, &slow_case);
-
- // Check the object's elements are in fast case and writable.
- __ movq(elements, FieldOperand(object, JSObject::kElementsOffset));
- __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
- Heap::kFixedArrayMapRootIndex);
- __ j(not_equal, &slow_case);
-
- // Check that both indices are smis.
- __ movq(index_1, Operand(rsp, 1 * kPointerSize));
- __ movq(index_2, Operand(rsp, 0 * kPointerSize));
- __ JumpIfNotBothSmi(index_1, index_2, &slow_case);
-
- // Check that both indices are valid.
- // The JSArray length field is a smi since the array is in fast case mode.
- __ movq(temp, FieldOperand(object, JSArray::kLengthOffset));
- __ SmiCompare(temp, index_1);
- __ j(below_equal, &slow_case);
- __ SmiCompare(temp, index_2);
- __ j(below_equal, &slow_case);
-
- __ SmiToInteger32(index_1, index_1);
- __ SmiToInteger32(index_2, index_2);
- // Bring addresses into index1 and index2.
- __ lea(index_1, FieldOperand(elements, index_1, times_pointer_size,
- FixedArray::kHeaderSize));
- __ lea(index_2, FieldOperand(elements, index_2, times_pointer_size,
- FixedArray::kHeaderSize));
-
- // Swap elements. Use object and temp as scratch registers.
- __ movq(object, Operand(index_1, 0));
- __ movq(temp, Operand(index_2, 0));
- __ movq(Operand(index_2, 0), object);
- __ movq(Operand(index_1, 0), temp);
-
- Label no_remembered_set;
- __ CheckPageFlag(elements,
- temp,
- 1 << MemoryChunk::SCAN_ON_SCAVENGE,
- not_zero,
- &no_remembered_set,
- Label::kNear);
- // Possible optimization: do a check that both values are Smis
- // (or them and test against Smi mask.)
-
- // We are swapping two objects in an array and the incremental marker never
- // pauses in the middle of scanning a single object. Therefore the
- // incremental marker is not disturbed, so we don't need to call the
- // RecordWrite stub that notifies the incremental marker.
- __ RememberedSetHelper(elements,
- index_1,
- temp,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
- __ RememberedSetHelper(elements,
- index_2,
- temp,
- kDontSaveFPRegs,
- MacroAssembler::kFallThroughAtEnd);
-
- __ bind(&no_remembered_set);
-
- // We are done. Drop elements from the stack, and return undefined.
- __ addq(rsp, Immediate(3 * kPointerSize));
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- __ jmp(&done);
-
- __ bind(&slow_case);
- __ CallRuntime(Runtime::kSwapElements, 3);
-
- __ bind(&done);
- context()->Plug(rax);
-}
-
-
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(2, args->length());
diff --git a/test/mjsunit/regress/regress-2071.js b/test/mjsunit/regress/regress-2071.js
new file mode 100644
index 0000000..91ae2a7
--- /dev/null
+++ b/test/mjsunit/regress/regress-2071.js
@@ -0,0 +1,79 @@
+// Copyright 2012 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.
+
+a = {};
+
+a.b = 42;
+
+with(a) {
+ a.f = (function f1() {
+ function f2() {
+ return b;
+ };
+ return f2;
+ })();
+}
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.f());
+}
+
+with(a) {
+ a.g = (function f1() {
+ function f2() {
+ function f3() {
+ return b;
+ }
+ return f3;
+ };
+ return f2();
+ })();
+}
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.g());
+}
+
+function outer() {
+ with(a) {
+ a.h = (function f1() {
+ function f2() {
+ function f3() {
+ return b;
+ }
+ return f3;
+ };
+ return f2();
+ })();
+ }
+};
+
+outer();
+
+for(var i = 0; i < 10000; i++) {
+ assertEquals(42, a.h());
+}
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 46f85fe..aa91139 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -58,31 +58,22 @@
# has some sources to link into the component.
'../../src/v8dll-main.cc',
],
+ 'defines': [
+ 'V8_SHARED',
+ 'BUILDING_V8_SHARED',
+ ],
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'V8_SHARED',
+ 'USING_V8_SHARED',
+ ],
+ },
'conditions': [
['OS=="mac"', {
'xcode_settings': {
'OTHER_LDFLAGS': ['-dynamiclib', '-all_load']
},
}],
- ['OS=="win"', {
- 'defines': [
- 'BUILDING_V8_SHARED',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'USING_V8_SHARED',
- ],
- },
- }, {
- 'defines': [
- 'V8_SHARED',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'V8_SHARED',
- ],
- },
- }],
['soname_version!=""', {
'product_extension': 'so.<(soname_version)',
}],
@@ -110,27 +101,16 @@
'dependencies': ['mksnapshot', 'js2c'],
}],
['component=="shared_library"', {
- 'conditions': [
- ['OS=="win"', {
- 'defines': [
- 'BUILDING_V8_SHARED',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'USING_V8_SHARED',
- ],
- },
- }, {
- 'defines': [
- 'V8_SHARED',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'V8_SHARED',
- ],
- },
- }],
+ 'defines': [
+ 'V8_SHARED',
+ 'BUILDING_V8_SHARED',
],
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'V8_SHARED',
+ 'USING_V8_SHARED',
+ ],
+ },
}],
],
'dependencies': [