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(&not_hi, NegateCondition(hi), scratch1, Operand(index1));
-  __ Branch(&slow_case, ls, scratch1, Operand(index2));
-  __ bind(&not_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': [